"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);
}
}
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的視圖上。
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()
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/
作者:我愛物聯網
出處:http://yydcdut.cnblogs.com/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。