>還在用Lisview?RecyclerView都已經出來一年多了!
想必大家多或多或少的接觸過或者了解過RecyclerView,為什么沒有用起來,原因大概如下?
- **ListView我用的挺好的,為什么要換RecyclerView?**
- **ListView穩定,熟悉,還知道很多開源庫,特別的好用!**
- **RecyclerView不能添加頭部,ListView能!**
-------------------
## RecyclerView
>RecyclerView最大的優勢就是靈活,RecyclerView只需改變一行代碼就可以變化多種不同的布局顯示排版,這一點對于開發者是非常方便的!
>>還有RecyclerView.Adapter,比BaseAdapter做了更好的封裝,把BaseAdapter的getView方法拆分成onCreateViewHolder方法和onBindViewHolder方法,強制需要創建ViewHolder,這樣的好處就是避免了初學者寫性能不佳的代碼
在Andorid 5.0出來不久,我就已經寫過RecyclerView的簡單介紹以及基本使用,不了解的可以看看[ListView升級版RecyclerView](http://blog.csdn.net/cym492224103/article/details/41719497),了解過的同學可以忽略,并往下看。
## 在實戰中我們會遇到什么問題?
>get到下面的技能就能夠在使用RcyclerView的大路上暢通無阻了!
- **添加分割線**
- **添加點按效果**
- **列表動畫**
- **改變某個數據保持當前位置**
- **添加頭部尾部**
- **列表分組**
- **各種效果集成Demo**
- **更靈活的RecyclerView**
####添加分割線
```
//通過以下方法添加分割線
mRecyclerView.addItemDecoration(new DividerItemDecoration(this,
DividerItemDecoration.VERTICAL_LIST));
```
需要RecyclerView.ItemDecoration這個抽象類實現一些方法
(后續有更偷懶的方法)
```
/**
* This class is from the v7 samples of the Android SDK. It's not by me!
* <p/>
* See the license above for details.
*/
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
Log.v("recyclerview - itemdecoration", "onDraw()");
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
```
看到這里應該有同學吐槽了,就添加一根線至于嗎?還需要重寫方法,ListView可是只需要簡單配置一下就好了。
```
android:divider="@color/grey"
android:dividerHeight="5dp"
```
為此我也感覺太麻煩,于是我想了一個辦法:
**直接在item_view里面底部自己添加一根線布局,這樣就無需重寫了,并且這樣還有個好處就是,如果細心的同學會發現,添加分割線,最后一個item下面不會有分割線,顯然當數據量不足一個屏幕的時候顯得很突兀,但是在item_view下面添加一個線的布局則不會出現這種情況**
####添加點按效果
RecyclerView直接在item_view里面配置即可
####動畫
>一個好的用戶體驗就是要有操作動畫的過渡,而不是生硬的刷新列表。
>>推薦一個RecyclerView的動畫庫([recyclerview-animators](https://github.com/wasabeef/recyclerview-animators))
>
RecyclerView自帶添加、刪除動畫,而ListView則需添加額外的代碼才能實現。
- **刪除調用RecyclerView的adapter的notifyItemRemoved**
- **添加調用RecyclerView的adapter的notifyItemInserted**
說到adapter我們就來說說RecyclerView.Adapter和BaseAdapter相比,額外提供了一下這些方法:
```
// 數據發生了改變,那調用這個方法,傳入改變對象的位置。
public final void notifyItemChanged(int position);
// 可以刷新從positionStart開始itemCount數量的item了
public final void notifyItemRangeChanged(int positionStart, int itemCount);
// 添加,傳入對象的位置。
public final void notifyItemInserted(int position);
// 刪除,傳入對象的位置。
public final void notifyItemRemoved(int position);
// 對象從fromPosition移動到toPosition
public final void notifyItemMoved(int fromPosition, int toPosition);
//批量添加
public final void notifyItemRangeInserted(int positionStart, int itemCount);
//批量刪除
public final void notifyItemRangeRemoved(int positionStart, int itemCount);
```
####改變列表某個布局狀態且保持當前位置
這種需求是普遍存在的,就是改變列表某一個item數據,然后刷新列表,如果是ListView刷新后則會回到最頂部,而RecyclerView同樣的操作但是原來滑動的位置不變。
##各種解決方案的RecyclerView的Adapter
[BaseRecyclerViewAdapterHelper](https://github.com/CymChad/BaseRecyclerViewAdapterHelper)

####更靈活的RecyclerView
[twoway-view](https://github.com/lucasr/twoway-view)
封裝了RecyclerView常用方法,如click等等,以及支持了更多不同的布局,使得RecyclerView使用起來更簡單!

>造起來!小伙伴們!
原文地址:[http://blog.csdn.net/cym492224103/article/details/51094982](http://blog.csdn.net/cym492224103/article/details/51094982)