編輯:關於Android編程
0. 前言
隨著Android的發展,雖然ListView依舊重要,但RecyclerView確實越來越多的被大家使用。但顯然並不能說RecyclerView就一定優於ListView,而是應該根據不同的需求選擇最合適的進行使用。本篇將介紹我們為什麼要使用RecyclerView,並且它的基本使用方法。
本文原創,轉載請注明出處為SEU_Calvin的博客。
1. 我們為什麼要使用RecyclerView
Google聲稱你可以把RecyclerView看成是升級版的ListView,為什麼ListView沒有被遺棄呢?到底RecyclerView強在哪裡了呢?
其實如果你只想簡單的使用滑動顯示這個功能,並且想輕松的使用divider,header,footer或者點擊事件這些功能,那麼使用ListView是完全沒有問題的。RecyclerView除了已經封裝好的Item復用機制外,的重點應該放在靈活性上,高度的解耦,這使得RecyclerView能夠實現深度的定制化,通過提供的不同LayoutManager,ItemDecoration,ItemAnimator等可以實現很多的效果。
(1)RecyclerView提供的三種布局管理器(LayoutManager),可以無縫銜接ListView、GridView,瀑布流的實現也變得簡單,滑動刪除和長按交換只需要添加幾個類就可以實現。
(2)ListView只有一個notifyDatasetChanged方法,想要做局部刷新還是挺麻煩的,但是在RecyclerView中,有很多適配局部刷新的API。
(3)RecyclerView實現Item增刪等動畫效果時,因為有了ItemAnimator因此要比ListView簡單的多。如果想定制Item之間的間隔,使用ItemDecoration也很方便。
(4)關於點擊事件,沒有像ListView那樣現成的API,但是自己封裝起來也不難,而且我們使用ListView時,如果item中有可點擊組件,那麼點擊事件的沖突也是一個問題,而在RecyclerView中則把點擊事件的控制權完全的交給開發者。
2. RecyclerView的簡單使用
2.1 Adapter中的實現
public class RecyclerAdapter extends RecyclerView.Adapter{ //… }
RecyclerView的Adapter需要繼承RecyclerView.Adapter
其中有幾個比較重要的方法需要實現,分別如下所示:
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { if (TYPE_ITEM == viewType) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); return new ViewHolder(v); } else { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_footer, viewGroup, false); return new ViewHolder(view); } } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { viewHolder.textView.setText(mData.get(i) + i); } @Override public int getItemCount() { return mData.size(); }
其中onCreateViewHolder()將布局轉化為View並傳遞給RecyclerView封裝好的ViewHolder,為了展示在RecyclerView中展示兩種布局的方式,做了兩種區分,即如果是RecyclerView的最後一個條目,則換一種布局展示。這裡簡單的設置兩個布局xml只是背景顏色不同,因此可以返回一樣的ViewHolder。而正常情況下可以新建另一個內部類FooterViewHolder extendsRecyclerView.ViewHolder,並在onCreateViewHolder()中進行區分返回。而這個例子中我們返回的ViewHolder是一個內部類。在其中進行控件的初始化。
public class ViewHolder extends RecyclerView.ViewHolder{ public TextView textView; public ViewHolder(View itemView) { super(itemView); textView = (TextView)itemView.findViewById(R.id.id_num); } }
在onCreateViewHolder(ViewGroup viewGroup, int viewType)中的第二個參數,就是進行類別區分的,和ListView類似,需要在Adapter內部重寫getItemViewType(intposition) 方法,實現哪個位置需要加載哪種布局的邏輯。如下例中,如果是最後一個條目,則返回一個代號。用於onCreateViewHolder()方法中進行具體的布局加載。
@Override public int getItemViewType(int position) { if (position + 1 == getItemCount()) { return TYPE_FOOTER; } else { return TYPE_ITEM; } }
有了ViewHolder之後,接下來就是要將ViewHolder和數據給綁定到一起來,在必須要實現的第二個方法onBindViewHolder(ViewHolder viewHolder,int i)中則建立起ViewHolder中視圖與數據的關聯。參數一個為對應的ViewHolder,一個為對應的位置。顯然如果需要展示不同的布局,在onBindViewHolder()中通過判斷viewHolder instanceof ViewHolder進行區分,對不同的布局中不同視圖進行不同的數據關聯。
最後getItemCount()是告知RecycleView,此Adapter到底要處理多少個對象。
2.2 Activity中的實現
mRcList = (RecyclerView) findViewById(R.id.rc_list); mLayoutManager = new LinearLayoutManager(this); mRcList.setLayoutManager(mLayoutManager); mRcList.setHasFixedSize(true); mSpinner = (Spinner) findViewById(R.id.spinner); mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { if (position == 0) { mRcList.setLayoutManager(new LinearLayoutManager(MainActivity.this)); //設置分隔線 mRcList.addItemDecoration(new DividerItemDecoration(MainActivity.this, DividerItemDecoration.VERTICAL)); } else if (position == 1) { mRcList.setLayoutManager(new GridLayoutManager(MainActivity.this, 3)); mRcList.addItemDecoration(new DividerGridItemDecoration(MainActivity.this)); }else if(position == 2){ //代表橫著有10行 mRcList.setLayoutManager(new StaggeredGridLayoutManager(10,StaggeredGridLayoutManager.HORIZONTAL)); mRcList.addItemDecoration(new DividerGridItemDecoration(MainActivity.this)); } } @Override public void onNothingSelected(AdapterView parent) { } });
這裡需要說明的是,現在SDK中提供了三種LayoutManager可以提供給RecyclerView使用,分別為LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager。本例中使用一個Spinner實現一個動態的切換效果。
在設置的分隔線時,LinearLayoutManager設置為了系統默認的分隔線,如12行所示。如果想自定義,則可以在style中加入
mRcList.setHasFixedSize(true)的作用查了一下,解釋如下:
//setHasFixedSize() is used to let the RecyclerView keep the same size. //This information will be used to optimize itself.
最後進行數據初始化以及設置Adapter:
for(int i=0; i<=20 ; i++){ mData.add("Recycler"); } mAdapter = new RecyclerAdapter(mData); mRcList.setAdapter(mAdapter);
從效果圖中可以看到,使用RecyclerView實現了兩種不同的布局,通過背景顏色進行區分。而且,可以動態的為RecyclerView設置三種不同的布局。並且當點擊主界面的刪除按鈕時,實現了刪除最後一個Item的操作,這裡notifyDataSetChanged()是通知Adapter數據發生了改變。
public void delRecycler(View view) { if (mData.size()> 0) { mData.remove(mData.size()- 1); mAdapter.notifyDataSetChanged(); } }
在上篇中我們已經實現了相機打開和實時圖像信息的獲取,那麼接下來我們可以嘗試在獲取的圖像信息進行一些處理,然後實時顯示出來,在這裡我們要完成的的幾種處理:灰化、Canny邊
本文實例講述了Android編程鬧鐘設置方法。分享給大家供大家參考,具體如下:鬧鐘在生活中最常見了,在Android中可以通過AlarmManager來實現鬧鐘,Alar
一. 再探Activity生命周期 為了研究activity的生命周期,簡單測試代碼如下。 package com.example.testactivity; impo
<?xml version=. encoding=UTF-?><RelativeLayout xmlns:android=http://