一、RecycleView的簡(jiǎn)介
RecyclerView是一種新的視圖組,目標(biāo)是為任何基于適配器的視圖提供相 似的渲染方式。該控件用于在有限的窗口中展示大量數(shù)據(jù)集,它被作為ListView和GridView控件的繼承者。 那么有了ListView、GridView為什么還需要RecyclerView這樣的控件呢?整體上看RecyclerView架構(gòu),提供了一種插拔式的體驗(yàn),高度的解耦,異常的靈活,通過(guò)設(shè)置它提供的不同LayoutManager,ItemDecoration, ItemAnimator實(shí)現(xiàn)令人瞠目的效果。
- 你想要控制其顯示的方式,請(qǐng)通過(guò)布局管理器LayoutManager
- 你想要控制Item間的間隔(可繪制),請(qǐng)通過(guò)ItemDecoration
- 你想要控制Item增刪的動(dòng)畫(huà),請(qǐng)通過(guò)ItemAnimator
- 你想要控制點(diǎn)擊、長(zhǎng)按事件,請(qǐng)自己寫(xiě)(擦,這點(diǎn)尼瑪。)
二、RecycleView的基本使用 1、在Gradle中引入RecycleView的依賴(lài)庫(kù)。 compile 'com.android.support:recyclerview-v7:23.1.1' 2、在布局文件當(dāng)中放置我們的RecycleView。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycle" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> 3、創(chuàng)建適配器類(lèi)繼承RecycleView的Adapter,步驟為:
- 繼承RecyclerView.Adapter,并且在Adapter里面聲明ViewHolder類(lèi)繼承RecyclerView.ViewHolder,最后把自己的ViewHolder類(lèi)丟進(jìn)自己的Adapter類(lèi)的泛型中去。
- 在自定義ViewHolder類(lèi)的構(gòu)造方法中可以通過(guò)ID找到布局的控件,控件需要聲明為自定義ViewHolder類(lèi)的成員變量。
- 實(shí)現(xiàn)RecyclerView.Adapter的所有未實(shí)現(xiàn)的函數(shù),onCreateViewHolder主要負(fù)責(zé)加載布局(加載的時(shí)候注意要把父布局寫(xiě)到參數(shù)里去),創(chuàng)建自定義ViewHolder類(lèi)的對(duì)象;onBindViewHolder主要負(fù)責(zé)把數(shù)據(jù)設(shè)置到Item的控件中;getItemCount主要負(fù)責(zé)得到數(shù)據(jù)的數(shù)目。
- 最好把數(shù)據(jù)聲明為成員變量,在構(gòu)造函數(shù)里面?zhèn)鬟M(jìn)來(lái)。
- 由于RecycleView原生不支持點(diǎn)擊事件,需要自己添加接口進(jìn)行回調(diào)。
代碼如下: public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { List<String> mDatas = null; Context mContext = null; //通過(guò)構(gòu)造函數(shù)把要顯示的數(shù)據(jù)讀取進(jìn)來(lái) public MyAdapter(List<String> mDatas, Context context) { this.mDatas = mDatas; this.mContext = context; } //相當(dāng)于ListView中的getView()方法 @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // View v = View.inflate(mContext,R.layout.item, null); LayoutInflater inflater = LayoutInflater.from(mContext); //加載布局的時(shí)候需要注意要把parent傳進(jìn)去 View v = inflater.inflate(R.layout.layout_item, parent, false); MyViewHolder holder = new MyViewHolder(v); return holder; } //在這里需要設(shè)置顯示的數(shù)據(jù) @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.tv_num.setText(mDatas.get(position)); } @Override public int getItemCount() { return mDatas.size(); } //自定義ViewHolder必須繼承RecyclerView.ViewHolder,在構(gòu)造函數(shù)中進(jìn)行ID綁定控件,條目監(jiān)聽(tīng)等 class MyViewHolder extendsRecyclerView.ViewHolder { TextView tv_num; public MyViewHolder(final View itemView) { super(itemView); tv_num = (TextView) itemView.findViewById(R.id.tv_num); tv_num.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onItemClickListener != null) { onItemClickListener.onItemClick(itemView, getLayoutPosition(), mDatas.get(getLayoutPosition())); } } }); } } //自定義監(jiān)聽(tīng) private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener listener) { this.onItemClickListener = listener; } public interface OnItemClickListener { void onItemClick(View v, int position, String data); } public void addData(int position, String data) { mDatas.add(position, data); notifyItemInserted(position); } public void removeData(int position) { mDatas.remove(position); notifyItemRemoved(position); } }
4、下面是MainActivity中需要進(jìn)行的處理。核心的步驟(某些步驟可不分先后)如下:
- 通過(guò)ID找到RecyclerView。
- RecyclerView設(shè)置Adapter。
- RecyclerView設(shè)置布局管理器,常用的布局管理器有LinearLayoutManager:線(xiàn)性布局,LayoutManager的實(shí)現(xiàn)類(lèi),類(lèi)型包括Vertical和HorizontalGridLayoutManager;格子布局,繼承自LinearLayoutManager,實(shí)現(xiàn)效果類(lèi)似GridView;StaggeredGridLayoutManager交錯(cuò)的格子布局,同樣也是LayoutManager的實(shí)現(xiàn)類(lèi),類(lèi)型包括Vertical和Horizontal,與GridLayoutManager很相似,不過(guò)是交錯(cuò)的格子,也就是寬高不等的格子視圖,類(lèi)似瀑布流的效果。
- RecyclerView設(shè)置數(shù)據(jù)插入、刪除的時(shí)候的動(dòng)畫(huà)效果,這里使用默認(rèn)的。下面的網(wǎng)址是GitHub上面的開(kāi)源動(dòng)畫(huà)效果:https://github.com/gabrielemariotti/RecyclerViewItemAnimators
- RecyclerView設(shè)置Item之間的裝飾器,這里也是使用GitHub提供的裝飾器,代碼會(huì)在附件中給出。
代碼如下: public class MainActivity extendsAppCompatActivity { List<String> datas = null; private RecyclerView recyclerView; private MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); recyclerView = (RecyclerView) findViewById(R.id.recycle); //設(shè)置RecycleView的適配器 myAdapter = new MyAdapter(datas, this); recyclerView.setAdapter(myAdapter); //設(shè)置布局管理器,以渲染出不同的效果 recyclerView.setLayoutManager(new LinearLayoutManager(this)); //設(shè)置插入、刪除數(shù)據(jù)的動(dòng)畫(huà)效果(這里使用默認(rèn)的動(dòng)畫(huà)) recyclerView.setItemAnimator(new DefaultItemAnimator()); //設(shè)置每個(gè)Item之間的裝飾(這里設(shè)置為分隔線(xiàn)) recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); //設(shè)置條目監(jiān)聽(tīng),需要自定義接口 myAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() { @Override public void onItemClick(View v, int position, String data) { Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show(); } }); } private void initData() { datas = new ArrayList<>(); for (int i = 0; i < 300; i++) { datas.add(i + ""); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_add: myAdapter.addData(0, "new data"); recyclerView.scrollToPosition(0); break; case R.id.action_delete: myAdapter.removeData(0); break; case R.id.action_gridview: recyclerView.setLayoutManager(new GridLayoutManager(this, 4)); break; case R.id.action_listview: recyclerView.setLayoutManager(new LinearLayoutManager(this)); break; case R.id.action_staggeredgridview: recyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL)); break; } return true; } }
三、運(yùn)行效果
先上圖三張,具體的一些動(dòng)畫(huà)效果需要自己體會(huì)。
對(duì)啦,notifyDataSetChanged方法以及棄用了,請(qǐng)注意RecycleView的新規(guī)矩:
notifyDataSetChanged()棄用
notifyItemChanged(intposition)
notifyItemInserted(intposition)
notifyItemMoved(intfromPosition, int toPosition)
notifyItemRemoved(intposition)
//range系列,多個(gè)item的操作
notifyItemRangeChanged(intpositionStart, int itemCount)
notifyItemRangeInserted(intpositionStart, int itemCount)
notifyItemRangeRemoved(intpositionStart, int itemCount)
補(bǔ)充:可以通過(guò)Adapter的getViewType(intposition)方法實(shí)現(xiàn)多種不同的條目。
具體做法是根據(jù)position的不同例如奇數(shù)偶數(shù),或者特定值,然后根據(jù)viewType參數(shù)的不同去inflate不同的item布局即可。
如下圖所示:
|