編輯:關於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();
}
}
OpenCV學習筆記(七)—— OpenCV for Android實時圖像處理
在上篇中我們已經實現了相機打開和實時圖像信息的獲取,那麼接下來我們可以嘗試在獲取的圖像信息進行一些處理,然後實時顯示出來,在這裡我們要完成的的幾種處理:灰化、Canny邊
Android編程鬧鐘設置方法詳解
本文實例講述了Android編程鬧鐘設置方法。分享給大家供大家參考,具體如下:鬧鐘在生活中最常見了,在Android中可以通過AlarmManager來實現鬧鐘,Alar
android --Activity生命周期詳解
一. 再探Activity生命周期 為了研究activity的生命周期,簡單測試代碼如下。 package com.example.testactivity; impo
Json數據解析模擬美團界面顯示
<?xml version=. encoding=UTF-?><RelativeLayout xmlns:android=http://