RecyclerView - 比 ListView 更強大易用效率高的滾動元件
雖然 ListView 可以完成我們大部分列表的需求,不過我們需要使用額外的方式來提高 ListView 的效率,然後 ListView 的擴展性也還不夠全面,它無法做到橫向滾動的效果,所以 Android 提供了一個更強大的元件 — RecyclerView
關於 RecyclerView
可以說是一個加強版的 ListView ,可以實現與 ListView 同樣的效果,也優化了 ListView 中其他不足的地方, Android 官方推薦使用 RecycleView ,也可以實現橫向滾動跟瀑布流佈局。
RecyclerView 基本用法
由於是新增的元件,為了讓Android所有的版本都能使用,將 RecyclerView 定義在了 support 庫當中,所以我們必須先在專案的 build.gradle 中添加相對應的依賴庫才行。
1 2 3 4 5 6 7 8 9 10 11
| dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12' }
|
我們在 dependencies 區塊中添加 compile 'com.android.support:recyclerview-v7:25.3.1' ,接著修改我們的 activity_main.xml 佈局代碼 :
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?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/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView> </LinearLayout>
|
RecyclerView Adapter
接著我們要實現與 ListView 相同的效果,所以我們直接延用之前的圖片及 Fruit 類別以及 layout 檔案,當然 RecyclerView 也跟 ListView 相同,需要一個 Adapter 類別,我們建立一個 FruitApapter :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private List<Fruit> mFruitList; static class ViewHolder extends RecyclerView.ViewHolder { ImageView fruitImage; TextView fruitName;
public ViewHolder(View view) { super(view); fruitImage = (ImageView) view.findViewById(R.id.fruit_image); fruitName = (TextView) view.findViewById(R.id.fruit_name); } }
public FruitAdapter(List<Fruit> fruitList) { mFruitList = fruitList; }
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.fruit_item, parent, false); ViewHolder holder = new ViewHolder(view); return holder; }
@Override public void onBindViewHolder(ViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); }
@Override public int getItemCount() { return mFruitList.size(); } }
|
首先,在這個 Adapter 中, 需要定義一個內部類別 ViewHolder , 它需要繼承 RecyclerView.ViewHolder 。 然後在這個 ViewHolder 的建構子中要傳入一個 View 參數,這個 View 通常都是指向 RecyclerView 子物件中的最外層佈局,接著我們就能用 findViewById() 方法來獲取佈局中的 ImageView 和 TextView 的實體。
FruitAdpater 中也有一個建構子,我們會將需要用到的資料透過建構子注入。由於是繼承 RecyclerView.ViewHolder ,我們必須實作三個 abstract 方法 onCreateViewHolder() 、 onBindViewHolder() 、 getItemCount() ,首先 onCreateViewHolder() 是用來建立 ViewHolder 實體,並把讀取出來的佈局傳入到建構子當中,最後回傳這個實體。 onBindViewHolder() 方法是用於對 RecyclerView 子物件的數據進行賦值,會在子物件出現在可顯示範圍中執行,這裡我們透過 position 參數得到目前的 Fruit 實體,然後再將數據設置到 ViewHolder 的 ImageView 和 TextView 。 getItemCount() 用來告訴 RecyclerView 有多少子元件,直接回傳顯示資料的筆數就可以了。
開始使用 RecyclerView
當我們準備好 Adapter 之後,我們就可以開始使用 RecyclerView 了 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits(); RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); FruitAdapter adapter = new FruitAdapter(fruitList); recyclerView.setAdapter(adapter); }
private void initFruits() { for(int i = 0; i < 2; i++) { Fruit apple = new Fruit("蘋果", R.drawable.apple_pic); fruitList.add(apple); Fruit banana = new Fruit("香蕉", R.drawable.banana_pic); fruitList.add(banana); Fruit orange = new Fruit("橘子", R.drawable.orange_pic); fruitList.add(orange); Fruit watermelon = new Fruit("西瓜", R.drawable.watermelon_pic); fruitList.add(watermelon); Fruit pear = new Fruit("梨子", R.drawable.pear_pic); fruitList.add(pear); Fruit grape = new Fruit("葡萄", R.drawable.grape_pic); fruitList.add(grape); Fruit pineapple = new Fruit("鳳梨", R.drawable.pineapple_pic); fruitList.add(pineapple); Fruit strawberry = new Fruit("草莓", R.drawable.strawberry_pic); fruitList.add(strawberry); Fruit cherry = new Fruit("櫻桃", R.drawable.cherry_pic); fruitList.add(cherry); Fruit mango = new Fruit("芒果", R.drawable.mango_pic); fruitList.add(mango);
} } }
|
這邊我們使用跟之前一樣的資料,所以一樣有 initFruits() 方法,接著我們在 onCreate() 方法中我們先拿到 RecyclerView 的實體,接著我們建立一個 LinearLayoutManager ,並設置到 RecyclerView 中,LayoutManager 用於指定 RecyclerView 的佈局方式,這裡使用的 LinearLayoutManager 是線性佈局的意思,接下來建立 FruitAdapter 實體,並且使用 RecyclerView 的 setAdapter 方法完成 Adapter 的設定。這樣就完成了整個 RecyclerView 的實現,並且能做到跟 ListVIew 一模一樣的效果。