編輯:關於android開發
RecyclerView是一種新的視圖組,目標是為任何基於適配器的視圖提供相似的渲染方式。它被作為ListView和GridView控件的繼承者,在最新的support-V7版本中提供支持。
在開發RecyclerView時充分考慮了擴展性,因此用它可以創建想到的任何種類的的布局。但在使用上也稍微有些不便。這就是Android——要完成一件事情總不是那麼容易。
整體上看RecyclerView架構,提供了一種插拔式的體驗,高度的解耦,異常的靈活,通過設置它提供的不同LayoutManager,ItemDecoration , ItemAnimator實現令人瞠目的效果。
RecyclerView可以實現以下功能:
ListView的功能
GridView的功能
橫向ListView的功能
橫向ScrollView的功能
瀑布流效果
便於添加Item增加和移除動畫
基本使用
引入官方提供的V7包
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
在java代碼中的聲明和普通控件是一樣的;
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new GridLayoutManager(this,2));
recyclerView.setAdapter(adapter);
setLayoutManager需要一個LayoutManager類,這個類有三個實現,分別是:
1.LinearLayoutManager 現行管理器,支持橫向、縱向
2.GridLayoutManager 網格布局管理器
3.StaggeredGridLayoutManager 瀑布就式布局管理器
上邊的代碼使用的是GridLayoutManager展示一個兩列的網格布局效果;
再來說說adapter,RecyclerView包含了一種新型適配器,它也需要使用ViewHolder,使用時需要重寫兩個主要方法:一個用來展現視圖和它的持有者的onCreateViewHolder(ViewGroup parent, int viewType),一個用來把數據綁定到視圖上的onBindViewHolder(ViewHolder holder, int position)。這麼做的好處是,onCreateViewHolder只有當我們真正需要創建一個新視圖時才被調用,不需要檢查它是否已經被回收。
adapter代碼:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.myViewHolder> {
private Context context;
private List<String> mDatas;
public RecyclerAdapter(Context context, List<String> mDatas) {
super();
this.context = context;
this.mDatas = mDatas;
}
@Override
public myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
myViewHolder holder = new myViewHolder(LayoutInflater.from(context).inflate(R.layout.item_home, parent, false));
return holder;
}
@Override
public void onBindViewHolder(final myViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class myViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public myViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.pos);
}
}
}
item代碼:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pos"
android:layout_width="144dip"
android:layout_height="72dip"
android:background="@color/colorPrimary"
android:gravity="center"
android:layout_margin="4dip"
android:textColor="#ffffff" />
之所以設置一個4dp的margin是因為RecyclerView並沒有為我們提供一個想listview那樣的設置分割線的屬性,所以可以在item中設置一個margin,當然你其實可以通過RecyclerView的addItemDecoration方法去自定義一個分割線。
運行上述代碼顯示效果:

使用LinearLayoutManager的顯示效果
recyclerView.setLayoutManager(new LinearLayoutManager(this));

使用StaggeredGridLayoutManager的顯示效果
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
使用StaggeredGridLayoutManager顯示瀑布流效果需要在adapter中隨機設置一下item的高度
adapter代碼
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.myViewHolder> {
private Context context;
private List<String> mDatas;
private List<Integer> mHeights;
public RecyclerAdapter(Context context, List<String> mDatas) {
super();
... ...
mHeights = new ArrayList<Integer>();
for (int i = 0; i < mDatas.size(); i++) {
mHeights.add((int) (100 + Math.random() * 300));
}
}
@Override
public void onBindViewHolder(final myViewHolder holder, int position) {
ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();
lp.height = mHeights.get(position);
holder.tv.setLayoutParams(lp);
... ...
}
其他代碼同上面的adapter一樣,這裡只貼出增加部分,運行效果如下:

上述代碼中StaggeredGridLayoutManager構造的第二個參數傳一個orientation,如果傳入的是StaggeredGridLayoutManager.VERTICAL代表有多少列;那麼傳入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行。例如改成
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL));
相應的Adapter中改成
@Override
public void onBindViewHolder(final myViewHolder holder, int position) {
ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();
lp.width = mHeights.get(position);
holder.tv.setLayoutParams(lp);
}
運行效果如下

這裡只貼了靜態圖,其實是可以水平滑動的。
再來說說item的動畫效果,RecyclerView 支持item的自定義動畫效果。github上也已經出現了好多自定義的效果,這裡貼出一個連接吧
https://github.com/wasabeef/recyclerview-animators
當然系統也為我們提供了一個默認的效果
recyclerView.setItemAnimator(new DefaultItemAnimator());
一句代碼即可,顯示效果如下

adapter中增加兩個方法
public void addData(int position) {
mDatas.add(position, "New Item");
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
Activity中調用一下
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_add:
adapter.addData(1);
break;
case R.id.action_delete:
adapter.removeData(1);
break;
}
return super.onOptionsItemSelected(item);
}
這裡需要注意的是RecyclerView 更新數據使用的是 notifyItemInserted(position)與notifyItemRemoved(position)這裡和listview的notifyDataSetChanged不同,雖然RecyclerView也提供notifyDataSetChanged方法,但使用notifyDataSetChanged是沒有任何動畫效果的。
由於RecyclerView的擴展行非常強,系統並沒有為我們提供setOnItemClickListener方法,這就需要我們自己去定義了,我們可以在adapter中自己去定義item回調接口
public interface OnItemClickLitener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickLitener mOnItemClickLitener;
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
this.mOnItemClickLitener = mOnItemClickLitener;
}
在onBindViewHolder中調用
@Override
public void onBindViewHolder(final myViewHolder holder, int position) {
... ...if (mOnItemClickLitener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int position=holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView,position);
return true;
}
});
}
}
Activity中添加以下代碼即可
adapter.setOnItemClickLitener(new RecyclerAdapter.OnItemClickLitener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, position + " click",Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(MainActivity.this, position + " LongClick",Toast.LENGTH_SHORT).show();
}
});
運行效果:

獻給那些還對RecyclerView還不太熟悉的兄弟們,需要源碼請留言。
參考資料
https://github.com/wasabeef/recyclerview-animators
http://blog.csdn.net/lmj623565791/article/details/45059587
http://blog.jobbole.com/74208/
提升Android ListView性能的幾個技巧
提升Android ListView性能的幾個技巧 ListView如何運作的? ListView是設計應用於對可擴展性和高性能要求的地方。實際上,這就意味著Lis
FFmpeg使用手冊 - FFmpeg 的編譯安裝
FFmpeg使用手冊 - FFmpeg 的編譯安裝FFMpeg在官方網站中提供了已經編譯好的可執行文件,用FFmpeg的人很多,因為FFmpeg是開源的,並且可以自己DI
自定義左下角弧形旋轉菜單欄
自定義左下角弧形旋轉菜單欄 要做這種效果 1- 整個自定義控件其實就是一個ArcMenu .(半圓形那一圈),左下角的圖標沒有加入進控件中。 2
MVP模式在Android項目中的使用,mvp模式android項目
MVP模式在Android項目中的使用,mvp模式android項目 以前在寫項目的時候,沒有過多考慮架構模式的問題,因為之前一直做J2EE開發,而J2EE都是采用MV
Android移動APP開發筆記——Cordova(PhoneGap)通過CordovaPlugin插件調用 Activity 實例,phonegapcordova
Android移動APP開發筆記——Cordova(PhoneGap)通