RecyclerView
創建列表與卡片
顯示一列項目一般會使用基本的ListView
或者GridView
。後來在supper library裏面增加了一個RecyclerView
,裏面封裝了更全面的功能,官方教程更推薦使用這個新的顯示列表項目的組件。
在一本書《Android編程權威教程》裏面介紹RecycleView的時候是這麼講的。假如一個列表有100項,每個項目包括1個TextView,那我們豈不是要準備100個TextView?這樣肯定會消耗大量資源。實際上,我們只需要準備剛好填滿屏幕的數量就好。RecyclerView顧名思義,就是可以把子View重複使用,只創建適應屏幕的數量,重複使用,可以節約資源。
除此以外,RecycleView還提供了一些有用的功能,比如可以在動態增加刪除資源的時候提供動畫效果等。這些我還沒有實踐過,僅測試了顯示功能。
開始使用
首先,需要在supper library裏面添加RecyclerView,然後就可以像普通的View一樣添加到Layout裏面去了。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_test_recycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.septem.firstapp.TestRecycleActivity">
<android.support.v7.widget.RecyclerView
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view_test"
android:background="#70b0e7" />
</RelativeLayout>
然後在程序裏添加
private void addViews() {
mRecyclerView = (RecyclerView)findViewById(R.id.recycler_view_test);
mLayoutManager = new GridLayoutManager(this,1);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyRecyclerAdapter();
mRecyclerView.setAdapter(mAdapter);
}
正如上面所寫,必須添加的項目包括
1,一個layoutManager
,一般情況是gridLayoutManager
或者LinearLayoutManager
.
2,一個Adapter
,用來添加數據
下面,需要定義一個MyRecyclerAdapter
private class MyRecyclerAdapter extends RecyclerView.Adapter<MyHolder> {
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ImageView iv = new ImageView(thisActivity);
LinearLayout.LayoutParams ivLayoutParams =
new LinearLayout.LayoutParams(300,
300);
ivLayoutParams.setMargins(5,5,0,0);
iv.setLayoutParams(ivLayoutParams);
iv.setBackgroundColor(Color.parseColor("#78daa8"));
iv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
//以上是代碼定義一個ImageView,也可以用XML定義,然後添加,如下
//View v = LayoutInflater.from(parent.getContext())
// .inflate(R.layout.my_text_view, parent, false);
MyHolder mHolder = new MyHolder(iv);
return mHolder;
}
@Override
public void onBindViewHolder(MyHolder holder, int position) {
mCursor.moveToFirst();
mCursor.move(position);
holder.iv.setImageBitmap(null);
LoadTask loadTask = new LoadTask();
loadTask.execute(position);
}
@Override
public int getItemCount() {
return mCursor.getCount();
}
}
自定義一個Adapter最少需要重寫3個方法,就是上面這3個
onCreateViewHolder
獲得一個viewHolder,是專門用於控制子View的,這裏需要在合適的地方建立一個新的類
private class MyHolder extends RecyclerView.ViewHolder {
public ImageView iv;
public MyHolder(View v) {
super(v);
this.iv = (ImageView) v;
}
}
這樣就可以創建一個最簡單的ViewHolder。之前在onCreateViewHolder裏面創建的子View被傳遞到這個裏面來。
onBindViewHolder(MyHolder holder, int position)
用於在子View裏面顯示數據,而子View是從參數的holder
裏面找到的
getItemCount()
用於獲取子View的個數
在以上設置好以後,一個最簡單的RecycleView就建立好了。
注意事項
一般會在一個單獨的線程裏面讀取數據,然後顯示出來,這時候,需要獲得對應Position的子View
ImageView iv = (ImageView)mLayoutManager.findViewByPosition(position);
還有一個方法,getChildAt(index)
也可以獲得子View,但是實際測試中發現經常出現錯誤。總結出原因是,這個方法返回的是屏幕可見的View。
比如,getChildAt(1)
返回屏幕上第2個可見的View。
而之前那個方法是我們需要的,就是返回整個列表中對應位置的View。這一點需要注意。
官網的文檔裏面居然沒寫清楚。
還有一個需要注意的,如果對應整個列表位置的View已經被移到屏幕外了,那麼這個View會返回爲null
,如果這時候對其操作會出現NullPointer exception
。所以,在操作的時候要判斷一下
if(iv!=null)
iv.setImageBitmap(bitmap);