快速掌握RecyclerView

過去的這一兩年, RecyclerView越來越引起了我們Android開發(fā)人員的注意,RecyclerView的靈活性還有性能上有很大的提升。
想必大家或多或少的接觸過或者了解過RecyclerView,為什么沒有用起來,原因大概如下?

  • 大家對于ListView的熟悉、,ListView基本可以滿足應用的大部分場景,為什么要換RecyclerView?
  • ListView穩(wěn)定,有很多相關開源庫,特別的好用。
  • RecyclerView不能添加頭布局,而ListView可以。

RecyclerView有什么優(yōu)缺點?如何使用RecyclerView和解決這些問題?

RecyclerView 的使用和優(yōu)點

  • 布局效果

RecyclerView最大的優(yōu)勢就是靈活,RecyclerView 同時支持 線性布局、網(wǎng)格布局瀑布流布局三種,而且還能夠控制橫向還是縱向滾動。

RecyclerView.LayoutManager,這是一個抽象類,系統(tǒng)提供了3個實現(xiàn)類:

  • LinearLayoutManager 線性管理器,支持橫向、縱向。
  • GridLayoutManager 網(wǎng)格布局管理器
  • StaggeredGridLayoutManager 瀑布就式布局管理器

注意:在實例化RecyclerView之后,我們需要使用setLayoutManager()給它設置布局管理器

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); // 創(chuàng)建線性布局管理器
      linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 設置線性布局為橫向(默認為縱向)
      mRecyclerView.setLayoutManager(linearLayoutManager); // 設置布局管理器
  • 自帶ViewHolder

    RecyclerView.Adapter,比BaseAdapter做了更好的封裝,強制需要創(chuàng)建ViewHolder,這樣的好處就是避免了初學者寫性能不佳的代碼

    繼承重寫 RecyclerView.Adapter 和 RecyclerView.ViewHolder

// 第一步:繼承重寫 RecyclerView.Adapter 和 RecyclerView.ViewHolder
public class AuthorRecyclerAdapter extends RecyclerView.Adapter<AuthorRecyclerAdapter.AuthorViewHolder> {

    @Override
    public AuthorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(AuthorViewHolder holder, int position) {

    }

    @Override
    public int getItemCount() {
        if (list == null) {
            return 0;
        }
        return list.size();
    }

    class AuthorViewHolder extends RecyclerView.ViewHolder {

        public AuthorViewHolder(View itemView) {
            super(itemView);

        }
    }
}
  • 控制item的間隔分割線,

可以使用addItemDecoration(ItemDecoration decor),不過里邊的ItemDecoration是一個抽象類,需要自己去實現(xiàn)

  • 實現(xiàn)增刪動畫

通過setItemAnimator(ItemAnimator animator)可以實現(xiàn)增刪動畫
RecyclerView自帶添加、刪除動畫,而ListView則需添加額外的代碼才能實現(xiàn)。

刪除調(diào)用RecyclerView的adapter的notifyItemRemoved
添加調(diào)用RecyclerView的adapter的notifyItemInserted

說到adapter我們就來說說RecyclerView.Adapter和BaseAdapter相比,額外提供了一下這些方法:

// 數(shù)據(jù)發(fā)生了改變,那調(diào)用這個方法,傳入改變對象的位置。
public final void notifyItemChanged(int position);
// 可以刷新從positionStart開始itemCount數(shù)量的item了
public final void notifyItemRangeChanged(int positionStart, int itemCount);
// 添加,傳入對象的位置。
public final void notifyItemInserted(int position);
// 刪除,傳入對象的位置。
public final void notifyItemRemoved(int position);
// 對象從fromPosition移動到toPosition
public final void notifyItemMoved(int fromPosition, int toPosition);
//批量添加
public final void notifyItemRangeInserted(int positionStart, int itemCount);
//批量刪除
public final void notifyItemRangeRemoved(int positionStart, int itemCount);

如何為RecyclerView添加Header和Footer

  • 在MyAdapter類中,提供setHeaderView()和setFooterView()兩個方法,我們就是通過這兩個方法從Activity將headerView和footerView傳遞過來的,利用getItemViewType()返回Item的類型,根據(jù)不同的類型,我們創(chuàng)建不同的Item的View。
package com.study.wnw.recyclerviewheaderfooter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/** * Created by wnw on 16-5-20. */
public class MyAdapter extendsRecyclerView.Adapter<RecyclerView.ViewHolder> {
   public static final int TYPE_HEADER = 0;  //說明是帶有Header的
   public static final int TYPE_FOOTER = 1;  //說明是帶有Footer的
   public static final int TYPE_NORMAL = 2;  //說明是不帶有header和footer的

   //獲取從Activity中傳遞過來每個item的數(shù)據(jù)集合
   private List<String> mDatas;
   //HeaderView, FooterView
   private View mHeaderView;
   private View mFooterView;

   //構造函數(shù)
   public MyAdapter(List<String> list){
       this.mDatas = list;
   }

   //HeaderView和FooterView的get和set函數(shù)
   public View getHeaderView() {
       return mHeaderView;
   }
   public void setHeaderView(View headerView) {
       mHeaderView = headerView;
       notifyItemInserted(0);
   }
   public View getFooterView() {
       return mFooterView;
   }
   public void setFooterView(View footerView) {
       mFooterView = footerView;
       notifyItemInserted(getItemCount()-1);
   }

   /** 重寫這個方法,很重要,是加入Header和Footer的關鍵,我們通過判斷item的類型,從而綁定不同的view    * */
   @Override
   public int getItemViewType(int position) {
       if (mHeaderView == null && mFooterView == null){
           return TYPE_NORMAL;
       }
       if (position == 0){
           //第一個item應該加載Header
           return TYPE_HEADER;
       }
       if (position == getItemCount()-1){
           //最后一個,應該加載Footer
           return TYPE_FOOTER;
       }
       return TYPE_NORMAL;
   }

    //創(chuàng)建View,如果是HeaderView或者是FooterView,直接在Holder中返回
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       if(mHeaderView != null && viewType == TYPE_HEADER) {
           return new ListHolder(mHeaderView);
       }
       if(mFooterView != null && viewType == TYPE_FOOTER){
           return new ListHolder(mFooterView);
       }
       View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
       return new ListHolder(layout);
   }

   //綁定View,這里是根據(jù)返回的這個position的類型,從而進行綁定的,   HeaderView和FooterView, 就不同綁定了
   @Override
   public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
       if(getItemViewType(position) == TYPE_NORMAL){
           if(holder instanceof ListHolder) {
               //這里加載數(shù)據(jù)的時候要注意,是從position-1開始,因為position==0已經(jīng)被header占用了
               ((ListHolder) holder).tv.setText(mDatas.get(position-1));
               return;
           }
           return;
       }else if(getItemViewType(position) == TYPE_HEADER){
           return;
       }else{
          return;
        }
     }

   //在這里面加載ListView中的每個item的布局
   class ListHolder extends RecyclerView.ViewHolder{
       TextView tv;
       public ListHolder(View itemView) {
           super(itemView);
           //如果是headerview或者是footerview,直接返回
           if (itemView == mHeaderView){
               return;
           }
           if (itemView == mFooterView){
               return;
           }
           tv = (TextView)itemView.findViewById(R.id.item);
        }
   }

   //返回View中Item的個數(shù),這個時候,總的個數(shù)應該是ListView中Item的個數(shù)加上HeaderView和FooterView
   @Override
   public int getItemCount() {
       if(mHeaderView == null && mFooterView == null){
           return mDatas.size();
       }else if(mHeaderView == null && mFooterView != null){
           return mDatas.size() + 1;
       }else if (mHeaderView != null && mFooterView == null){
           return mDatas.size() + 1;
       }else {
           return mDatas.size() + 2;
       }
   }
}
  • 在Activity添加布局
mMyAdapter.setHeaderView(header);
mMyAdapter.setFooterView(footer);

如何給RecyclerView添加點擊事件

RecyclerView強大,好用,但是使用率很高的ItemClickListener卻沒有添加。

點擊事件的實現(xiàn),有常見的三種方法:

  • 通過 RecyclerView已有的方法 addOnItemTouchListener()實現(xiàn)
  • 在創(chuàng)建 ItemView時添加點擊監(jiān)聽
  • 當 ItemViewattach RecyclerView時實現(xiàn)

具體參考:給RecyclerView封裝個Adapter吧(更優(yōu)雅的添加點擊事件)

更多功能介紹將持續(xù)更新中。。。。。。

參考文獻 及相關框架:

基礎篇:

擴展:

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容