Android -- RecyclerView

來源:互聯網
上載者:User

標籤:

"A flexible view for providing a limited window into a large data set."

可以說是ListView的升級版,ListVie中我們需要自己寫ViewHolder,當然你也可以不寫,是在RecylerView中,是要讓寫的喲~RecyclerView適用於無法在一個螢幕範圍內展現格式一樣的資料時,需要用多行或多列來展示。例如展示連絡人,圖片,視頻等。使用者需要滑動螢幕來查看資料,這時RecyclerView的特性就有用武之地了。比如,當使用者滑動使當前一個可視的Item滑出螢幕,這個Item的視圖將會被回收並在一個新Item進入可視範圍後重新被使用。可回收利用View是個很實用的功能,它不僅可以減少CPU不斷inflate View的開銷,而且可以節省緩衝View的記憶體開銷。

RecylerView還有一大特色,就是動畫!

RecyclerView不再負責顯示工作

和ListView不一樣的是,RecyclerView不再負責Item的擺放等顯示方面的功能。所有和布局、繪製等方面的工作都其拆分成不同的類進行管理。所以開發人員可以自訂各種各樣滿足定製需求的的功能類。

RecyclerView.Adapter

管理的資料集合,為每個Item建立視圖
RecyclerView.ViewHolder 承載Item視圖的子視圖
RecyclerView.LayoutManager 負責Item視圖的布局
RecyclerView.ItemDecoration 為每個Item視圖添加子視圖,在Demo中被用來繪製Divider
RecyclerView.ItemAnimator 負責添加、刪除資料時的動畫效果
ViewHolder

關於ViewHolder,Google早就推薦開發人員使用,但也只是建議。但是現在,RecyclerView.Adapter最終要求開發人員必須使用ViewHolder。

public class MyViewHolder extends ViewHolder{        public ImageView iv;      public TextView tv;            public MyViewHolder(View rootView) {          super(rootView);          iv = (ImageView)rootView.findViewById(R.id.item_iv);          tv = (TextView)rootView.findViewById(R.id.item_tv);      }  }
RecyclerView.Adapter

Adapter負責扮演兩個角色:不僅為底部資料提供支援而且還負責為資料建立合適的視圖。Adapter適用在Android很多控制項,例如ListView、AutoCompleteTextView等。

public class MyAdapter extends Adapter<MyViewHolder> {        private List<Item> mData;            public MyAdapter(List<Item> data){          this.mData = data;      }            @Override      public int getItemCount() {          return mData.size();      }              @Override      public void onBindViewHolder(MyViewHolder holder, int position) {          Item bean = mData.get(position);          holder.tv.setText(bean.tv);      }        @Override      public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {          View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent,false);          MyViewHolder vh = new MyViewHolder(itemView);          return vh;      }
}

onCreateViewHolder中負責為Item建立視圖,onBindViewHolder負責將資料繫結到Item的視圖上。

RecyclerView.LayoutManager

LayoutManager是RecyclerView中最有意思的類。該類負責將每個Item視圖在RecylerView中的布局。目前Google提供了LayoutManager的一個子類:LinearLayoutManager。LinearLayoutManager提供了橫向和豎向兩種布局。

MyLayoutManager manager = new MyLayoutManager(this);  manager.setOrientation(LinearLayout.HORIZONTAL);//預設是LinearLayout.VERTICAL  mRecyclerView.setLayoutManager(manager);

LinearLayoutManager提供了如下幾個方法來協助開發人員擷取螢幕上的頂部item和底部item:

  • findFirstVisibleItemPosition()
  • findFirstCompletelyVisibleItemPosition()
  • findLastVisibleItemPosition()
  • findLastCompletelyVisibleItemPosition()

    RecyclerView.ItemDecoration

    通過ItemDecoration可以使各個Item在視覺上相互分開,其實和ListView的Divider很像。ItemDecoration並不是RecyclerView必須設定的,開發人員可以不設定或者設定多個Decoration。RecyclerView會遍曆所有的ItemDecoration並調用各自的繪圖方法。

    public class MyDecoration extends ItemDecoration {        private static final int[] ATTRS = new int[]{          android.R.attr.listDivider      };            private Drawable mDivider;            public MyDecoration(Context ctx){          final TypedArray a = ctx.obtainStyledAttributes(ATTRS);          mDivider = a.getDrawable(0);      }            @Override      public void onDraw(Canvas c, RecyclerView parent, State state) {          int top = parent.getPaddingTop();          int bottom = parent.getHeight() - parent.getPaddingBottom();          int childCount = parent.getChildCount();          for(int i=0;i < childCount;i++){              View child = parent.getChildAt(i);              RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams)child.getLayoutParams();              int left = child.getRight() + layoutParams.rightMargin;              int right = left + mDivider.getIntrinsicWidth();              mDivider.setBounds(left, top, right, bottom);              mDivider.draw(c);          }      }            @Override      public void getItemOffsets(Rect outRect, View view, RecyclerView parent,  State state) {          outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);      }        }
    RecyclerView.ItemAnimatior
    • 刪除某一個Item
    • 添加一個新的Item
    • 移動某個Item

    Google提供了一個名為DefaultItemAnimator的預設ItemAnimator供開發人員使用。如果開發人員不為RecyclerView設定ItemAnimator,RecyclerView也會使用預設的DefaultItemAnimator。
    顯然,為了讓動畫效果起效,開發人員必須通知Adapter資料有改變。之前我們使用Adapter時會調用notifyDataSetChanged()來通知Adapter資料改變並更新視圖,現在RecyclerView,Adapter提供了許多notifyXyz()方法。

    流程
    • 執行個體化RecyclerView
    • 為RecyclerView設定LayoutManager
    • 為RecyclerView設定Adapater
    • 如果有需求,可以設定一個或多個ItemDecorations,當然,也可以不設定
    • 如果有需求,可以設定ItemAnimator
    監聽事件

    RecyclerView不再負責Item視圖的布局及顯示,所以RecyclerView也沒有為Item開放OnItemClick等點擊事件,這就需要開發人員自己實現。

    因為ViewHolder我們可以拿到每個Item的根布局,所以如果我們為根布局設定單獨的OnClick監聽並將其開放給Adapter,那不就可以在組裝RecyclerView時就能夠設定ItemClickListener,只不過這個Listener不是設定到RecyclerView上而是設定到Adapter。

    public class MyViewHolder extends ViewHolder implements OnClickListener,OnLongClickListener{        public ImageView iv;      public TextView tv;      private MyItemClickListener mListener;      private MyItemLongClickListener mLongClickListener;            public MyViewHolder(View rootView,MyItemClickListener listener,MyItemLongClickListener longClickListener) {          super(rootView);          iv = (ImageView)rootView.findViewById(R.id.item_iv);          tv = (TextView)rootView.findViewById(R.id.item_tv);          this.mListener = listener;          this.mLongClickListener = longClickListener;          rootView.setOnClickListener(this);          rootView.setOnLongClickListener(this);      }        /**      * 點擊監聽      */      @Override      public void onClick(View v) {          if(mListener != null){              mListener.onItemClick(v,getPosition());          }      }        /**      * 長按監聽      */      @Override      public boolean onLongClick(View arg0) {          if(mLongClickListener != null){              mLongClickListener.onItemLongClick(arg0, getPosition());          }          return true;      }    }
    item長寬
    public class MyLayoutManager extends LinearLayoutManager {        public MyLayoutManager(Context context) {          super(context);      }              @Override      public void onMeasure(Recycler recycler, State state, int widthSpec,int heightSpec) {          View view = recycler.getViewForPosition(0);          if(view != null){              measureChild(view, widthSpec, heightSpec);              int measuredWidth = MeasureSpec.getSize(widthSpec);              int measuredHeight = view.getMeasuredHeight();              setMeasuredDimension(measuredWidth, measuredHeight);          }      }  }
    我是天王蓋地虎的分割線

     

     

     

     

    參考:http://www.grokkingandroid.com/first-glance-androids-recyclerview/

Android -- RecyclerView

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.