国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android中封裝RecyclerView實現添加頭部和底部示例代碼

2019-10-22 18:29:33
字體:
來源:轉載
供稿:網友

前言

我們大家都知道ListView具有添加android/238177.html">頭部和添加底部的方法,但是RecyclerView并沒有這樣子的方法。所以RecyclerView是不能添加底部和頭部的,但是能不能仿造ListView來實現RecyclerView添加頭部和底部呢?答案當然是可行的。本文就來給大家介紹了關于Android封裝RecyclerView添加頭部和底部的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

首先看下實現的效果:

recyclerview添加頭部,recyclerview,頭部,android

代碼如下:

public class WrapMyRecyclerView extends RecyclerView { private Adapter mAdapter; private ArrayList<View> mHeaderViewInfos = new ArrayList<>();//保存headerView private ArrayList<View> mFooterViewInfos = new ArrayList<>();//保存footerView public WrapMyRecyclerView(Context context) {  super(context); } public WrapMyRecyclerView(Context context, @Nullable AttributeSet attrs) {  super(context, attrs); } public WrapMyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle); } /**  * 添加headerView  * @param v  */ public void addHeaderView(View v) {  mHeaderViewInfos.add(v);  // Wrap the adapter if it wasn't already wrapped.  if (mAdapter != null) {   if (!(mAdapter instanceof RecyclerHeaderViewListAdapter)) {    wrapHeaderListAdapterInternal();   }  } } /**  * 添加一個footerView  * @param v  */ public void addFooterView(View v) {  mFooterViewInfos.add(v);  // Wrap the adapter if it wasn't already wrapped.  if (mAdapter != null) {   if (!(mAdapter instanceof RecyclerHeaderViewListAdapter)) {    wrapHeaderListAdapterInternal();   }  } } /**  * 設置一個Adapter  * @param adapter  */ @Override public void setAdapter(Adapter adapter) {  if (mHeaderViewInfos.size() > 0 || mFooterViewInfos.size() > 0) {   mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);  } else {   mAdapter = adapter;  }  super.setAdapter(mAdapter); } private void wrapHeaderListAdapterInternal() {  mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, mAdapter); } /**  * 新建一個RecyclerHeaderViewListAdapter對象  * 最終的adapter實現它  * @param headerViewInfos  * @param footerViewInfos  * @param adapter  * @return  */ protected RecyclerHeaderViewListAdapter wrapHeaderListAdapterInternal(   ArrayList<View> headerViewInfos,   ArrayList<View> footerViewInfos,   Adapter adapter) {  return new RecyclerHeaderViewListAdapter(headerViewInfos, footerViewInfos, adapter); }}

這就是封裝的RecyclerView,里面主要有三個方法addHeaderView、 addFooterView和重寫的setAdapter。這里的唯一的思想就是偷梁換柱,當我們添加頭部、尾部或者設置adapter時,真正的adapter并不是我們傳入的adapter,而是重新new 了一個RecyclerHeaderViewListAdapter。這才是RecyclerView最終設置的adapter。

其實我們看到ListView也是通過這樣子的思想來添加頭部和尾部的。

recyclerview添加頭部,recyclerview,頭部,android

這就是ListView的addHeaderView方法,它會偷偷的創建HeaderViewListAdapter這個adapter。最終添加的header和footer在HeaderViewListAdapter里面實現。

public class RecyclerHeaderViewListAdapter extends RecyclerView.Adapter { private final ArrayList<View> mHeaderViewInfos;//保存headerview數據 private final ArrayList<View> mFooterViewInfos;//保存footerView數據 private RecyclerView.Adapter mAdapter;   //用戶自己構造的adapter private static final int RECYCLER_HEADER_VIEW = 0x001;//headerview類型 private static final int RECYCLER_FOOTER_VIEW = 0x002;//footerView類型 /**  * 構造方法  * 初始化  * @param headerViewInfos  * @param footerViewInfos  * @param adapter  */ public RecyclerHeaderViewListAdapter(ArrayList<View> headerViewInfos,           ArrayList<View> footerViewInfos,           RecyclerView.Adapter adapter) {  mAdapter = adapter;  if (headerViewInfos == null) {   mHeaderViewInfos = new ArrayList<>();  } else {   mHeaderViewInfos = headerViewInfos;  }  if (footerViewInfos == null) {   mFooterViewInfos = new ArrayList<>();  } else {   mFooterViewInfos = footerViewInfos;  } } /**  * 根據getItemViewType返回的條目類型  * 創建不同的itemview  * 傳入的adapter,回調它的onCreateViewHolder即可  * @param parent  * @param viewType  * @return  */ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  if (viewType == RECYCLER_HEADER_VIEW){   return new HeaderViewLayout(mHeaderViewInfos.get(0));  }else if (viewType == RECYCLER_FOOTER_VIEW){   return new HeaderViewLayout(mFooterViewInfos.get(0));  }  return mAdapter.onCreateViewHolder(parent,viewType); } /**  * 綁定數據  * headerview和footerview不需要綁定數據,直接return即可  * 傳入的adapter需要回調它的onBindViewHolder即可  * @param holder  * @param position  */ @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  //header  int numHeaders = getHeadersCount();  if (position < numHeaders) {   return ;  }  //adapter body  final int adjPosition = position - numHeaders;  int adapterCount = 0;  if (mAdapter != null) {   adapterCount = mAdapter.getItemCount();   if (adjPosition < adapterCount) {    mAdapter.onBindViewHolder(holder, adjPosition);    return ;   }  }  //footer } /**  * 返回條目的類型  * 傳入的adapter,回調它的getItemViewType即可  * @param position  * @return  */ @Override public int getItemViewType(int position) {  // Header  int numHeaders = getHeadersCount();  if (position < numHeaders) {   return RECYCLER_HEADER_VIEW;  }  // Adapter  final int adjPosition = position - numHeaders;  int adapterCount = 0;  if (mAdapter != null) {   adapterCount = mAdapter.getItemCount();   if (adjPosition < adapterCount) {    return mAdapter.getItemViewType(position);   }  }  // Footer (off-limits positions will throw an IndexOutOfBoundsException)  return RECYCLER_FOOTER_VIEW; } /**  * 總條目即:footerview的條目+headerview的條目+穿入的adapter條目  * @return  */ @Override public int getItemCount() {  if (mAdapter != null) {   return getFootersCount() + getHeadersCount() + mAdapter.getItemCount();  } else {   return getFootersCount() + getHeadersCount();  } } /**  * 獲取headerview的條目  * @return  */ public int getHeadersCount() {  return mHeaderViewInfos.size(); } /**  * 獲取footervie的條目  * @return  */ public int getFootersCount() {  return mFooterViewInfos.size(); } /**  * 這是footerview和headerview的ViewHolder需要  * 這里只是提供一個構造器即可,實際上用處不大  */ private static class HeaderViewLayout extends RecyclerView.ViewHolder{  public HeaderViewLayout(View itemView) {   super(itemView);  } }}

這是實現添加header、footer和傳入adapter的RecyclerHeaderViewListAdapter。具體的邏輯都在文件的注釋里面有說明。邏輯是仿造ListView的HeaderViewListAdapter來實現的。

其實就是創建一個adapter,然后根據不同的條目類型來創建條目和綁定條目的數據即可。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.wrap.recycler.WrapRecyclerViewActivity"> <com.lwj.wrap.recycler.WrapMyRecyclerView  android:id="@+id/wrap_recyclerview"  android:layout_width="match_parent"  android:layout_height="match_parent"/></LinearLayout>

這是布局文件

public class WrapRecyclerViewActivity extends AppCompatActivity { private WrapMyRecyclerView mRecyclerView; private MyAdapter mMyAdapter; private List<String> mList01 = new ArrayList<>(); private static final int WC = ViewGroup.LayoutParams.WRAP_CONTENT; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_wrap_recycler_view);  getData();  mRecyclerView = (WrapMyRecyclerView) this.findViewById(R.id.wrap_recyclerview);  mRecyclerView.setLayoutManager(new LinearLayoutManager(this));  //加入headerView  ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(WC,WC);  ImageView headerView = new ImageView(this);  headerView.setImageResource(R.drawable.timg);  headerView.setLayoutParams(params);  mRecyclerView.addHeaderView(headerView);  //設置adapter  mMyAdapter = new MyAdapter(this,mList01);  mRecyclerView.setAdapter(mMyAdapter);  //加入footerView  params = new ViewGroup.LayoutParams(WC,WC);  ImageView footerView = new ImageView(this);  footerView.setImageResource(R.drawable.hhfj);  footerView.setLayoutParams(params);  mRecyclerView.addFooterView(footerView);  mMyAdapter.notifyDataSetChanged(); } public void getData() {  for (int i = 0; i < 3; i++) {   String data ="adapter...." + i;   mList01.add(data);  } }}

使用直接調用addHeaderView、addFooterView即可。

除了這種方式來實現addHeaderView和addFooterView,另外一種方式就是封裝Adapter來實現,原理還是保持不變:根據不同的條目類型來創建條目和綁定條目的數據。

public class MyCircleRecycViewAdapter extends RecyclerView.Adapter { public List<CircleInfo.CirclePageInfo> infos = null; private Context mContext; private ListViewImgLoader mLoader; private View VIEW_FOOTER;//尾部 private View VIEW_HEADER;//頭部 //Type private int TYPE_NORMAL = 1000; private int TYPE_HEADER = 1001; private int TYPE_FOOTER = 1002; private int tagType = TYPE_NORMAL; public MyCircleRecycViewAdapter(Context context,List<CircleInfo.CirclePageInfo> datas) {  this.infos = datas;  this.mContext = context;  mLoader = new ListViewImgLoader();  mLoader.setMemoryCacheSize(1024 * 1024);  mLoader.setVisibleItemCount(12); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  if (viewType == TYPE_FOOTER) {   tagType = TYPE_FOOTER;   return new MyCircleItemHolder(VIEW_FOOTER);  } else if (viewType == TYPE_HEADER) {   tagType = TYPE_HEADER;   return new MyCircleItemHolder(VIEW_HEADER);  } else {   tagType = TYPE_NORMAL;   View view = LayoutInflater.from(mContext).inflate(R.layout.circle_gridview_items, parent,false);   return new MyCircleItemHolder(view);  } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  if (!isHeaderView(position) && !isFooterView(position)) {   if (haveHeaderView()) position--;   MyCircleItemHolder viewHolder = (MyCircleItemHolder)holder;   CircleInfo.CirclePageInfo mInfo = infos.get(position);   setData(viewHolder,mInfo);  } } @Override public int getItemCount() {  int count = (infos == null ? 0 : infos.size());  if (VIEW_FOOTER != null) {   count++;  }  if (VIEW_HEADER != null) {   count++;  }  return count; } @Override public int getItemViewType(int position) {  if (isHeaderView(position)) {   return TYPE_HEADER;  } else if (isFooterView(position)) {   return TYPE_FOOTER;  } else {   return TYPE_NORMAL;  } } public void addHeaderView(View headerView) {  if (haveHeaderView()) {   throw new IllegalStateException("hearview has already exists!");  } else {   //避免出現寬度自適應   ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(Utils.getRealPixel(30), Utils.getRealPixel(230));   headerView.setLayoutParams(params);   VIEW_HEADER = headerView;   notifyItemInserted(0);  } } public void addFooterView(View footerView) {  if (haveFooterView()) {   throw new IllegalStateException("footerView has already exists!");  } else {   ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);   footerView.setLayoutParams(params);   VIEW_FOOTER = footerView;//   ifGridLayoutManager();   notifyItemInserted(getItemCount() - 1);  } } private boolean haveHeaderView() {  return VIEW_HEADER != null; } public boolean haveFooterView() {  return VIEW_FOOTER != null; } private boolean isHeaderView(int position) {  return haveHeaderView() && position == 0; } private boolean isFooterView(int position) {  return haveFooterView() && position == getItemCount() - 1; } private void setData(final MyCircleItemHolder viewHolder, final CircleInfo.CirclePageInfo mInfo) {  if(mInfo == null || mInfo == viewHolder.tagInfo)  {   return;  }else{   viewHolder.tagInfo = mInfo;   if(!StrUtils.isEnpty(mInfo.thread_unread)){    if(mInfo.thread_unread.equals("0")){     viewHolder.threaduUnreadTv.setVisibility(View.INVISIBLE);    }else{     viewHolder.threaduUnreadTv.setVisibility(View.VISIBLE);     viewHolder.threaduUnreadTv.setText(mInfo.thread_unread);    }   }else{    viewHolder.threaduUnreadTv.setVisibility(View.INVISIBLE);   }   if (!TextUtils.isEmpty(viewHolder.tagUrl)){    if(mInfo.circle_img_path != null && !(mInfo.circle_img_path.equals(viewHolder.tagUrl))){     setImage(viewHolder.mImageView,mInfo.circle_img_path);    }   }else{    setImage(viewHolder.mImageView,mInfo.circle_img_path);   }   if (!TextUtils.isEmpty(mInfo.circle_img_path)){    viewHolder.tagUrl = mInfo.circle_img_path;   }   if(mInfo.circleName != null){    if(mInfo.circleName.length() > 5){     String s = mInfo.circleName.substring(0,5) + "...";     viewHolder.textView.setText(s);    }else{     viewHolder.textView.setText(mInfo.circleName);    }   }  } } private void setImage(final ColorFilterImageView mImageView, final String imgUrl){  mImageView.setBackgroundColor(0xffadadad);  mImageView.setImageBitmap(null);  if(!TextUtils.isEmpty(imgUrl))  {   mLoader.loadImage(mImageView.hashCode(), imgUrl, 300, new DnImg.OnDnImgListener()   {    @Override    public void onProgress(String url, int downloadedSize, int totalSize)    {     // TODO Auto-generated method stub    }    @Override    public void onFinish(String url, String file, Bitmap bmp)    {     if(url.equals(imgUrl))     {      mImageView.setImageBitmap(bmp);     }    }   });  }else{   mImageView.setBackgroundColor(0xffadadad);   mImageView.setImageBitmap(null);  } } class MyCircleItemHolder extends RecyclerView.ViewHolder{  private ColorFilterImageView mImageView;  private TextView textView;  private CircleInfo.CirclePageInfo tagInfo;  private String tagUrl;  private TextView threaduUnreadTv;  public MyCircleItemHolder(final View itemView) {   super(itemView);   if(tagType == TYPE_NORMAL){    mImageView = (ColorFilterImageView)itemView.findViewById(R.id.quan_icon);    mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);    textView = (TextView)itemView.findViewById(R.id.quan_name);    threaduUnreadTv = (TextView)itemView.findViewById(R.id.quan_num);    mImageView.setOnClickListener(new View.OnClickListener() {     @Override     public void onClick(View v) {      if (mListener != null){       mListener.oncliItem(itemView,tagInfo,threaduUnreadTv);      }     }    });   }  } } public OnclickMyCircleItemListener mListener; public void setOnclickMyCircleItemListener(OnclickMyCircleItemListener l){  this.mListener = l; } public interface OnclickMyCircleItemListener{  void oncliItem(View view,CircleInfo.CirclePageInfo info,View threadNumTv); } public void pauseLoader(){  if(mLoader != null)  {   mLoader.pause();  } } public void resumeLoader(){  if(mLoader != null)  {   mLoader.resume();  } } public void closeLoader(){  if(mLoader != null)  {   mLoader.close();  } }}

總結

以上就是這篇文章的全部內容了,希望本文的內容對各位Android開發者們的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 和静县| 温宿县| 师宗县| 鹤庆县| 香港| 大姚县| 望江县| 池州市| 安乡县| 和田县| 江陵县| 荃湾区| 富川| 瓦房店市| 客服| 秦皇岛市| 突泉县| 丰台区| 谷城县| 区。| 永宁县| 五大连池市| 通州市| 临泽县| 肥西县| 永寿县| 桐庐县| 赫章县| 格尔木市| 平安县| 八宿县| 德阳市| 利辛县| 手游| 当雄县| 瓮安县| 贵州省| 青铜峡市| 龙胜| 福贡县| 平潭县|