這是之前保存的學習筆記, 現在上傳保存一下
RecycleView
參考 Android RecyclerView 使用完全解析 體驗藝術般的控件
和
RecycleView的基本使用
概述
RecycleView 在 support-v7包下
其作用是用來代替 ListView和GridView
其優點是:
提供了一種插拔式的體驗,高度的解耦,異常的靈活,通過設置它提供的不同LayoutManager,ItemDecoration , ItemAnimator實現令人瞠目的效果。
例如:
1,你想要控制其顯示的方式,請通過佈局管理器LayoutManager
2,你想要控制Item間的間隔(可繪製),請通過ItemDecoration
3,你想要控制Item增刪的動畫,請通過ItemAnimator
缺點是:
想要實現點擊、長按事件,需要自己定義
基本使用方法
mRecyclerView = findView(R.id.id_recyclerview);
//設置佈局管理器
mRecyclerView.setLayoutManager(layout);
//設置adapter
mRecyclerView.setAdapter(adapter)
//設置Item增加、移除動畫
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割線
mRecyclerView.addItemDecoration(new DividerItemDecoration(
getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
Just like ListView(主要流程的代碼)
主界面:
recyclerView = (RecyclerView) findViewById(gridRv);
initData();
//設置佈局適配器
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//設置adapter
mAdapter = new RecycleViewListAdapter(this, mDatas);
recyclerView.setAdapter(mAdapter);
adapter:
public class RecycleViewListAdapter extends RecyclerView.Adapter {
private List<String> mDatas;
private Context mContext;
public RecycleViewListAdapter(Context mContext, List<String> mDatas) {
this.mContext = mContext;
this.mDatas = mDatas;
}
public void setImages(List<String> mDatas) {
this.mDatas = mDatas;
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_list_recycleview, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
myViewHolder.tv.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public MyViewHolder(View view) {
super(view);
tv = (TextView) view.findViewById(R.id.recy_tv);
}
}
}
ItemDecoration(添加分割線)
主要方法爲: mRecyclerView.addItemDecoration(ItemDecoration)
該方法的參數爲RecyclerView.ItemDecoration,該類爲抽象類,該類的源碼爲:
public static abstract class ItemDecoration {
public void onDraw(Canvas c, RecyclerView parent, State state) {
onDraw(c, parent);
}
public void onDrawOver(Canvas c, RecyclerView parent, State state) {
onDrawOver(c, parent);
}
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
parent);
}
@Deprecated
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent){
outRect.set(0, 0, 0, 0);
}
}
當我們調用mRecyclerView.addItemDecoration(ItemDecoration)方法添加decoration的時候,RecyclerView在繪製的時候,去會繪製decorator,即調用該類的onDraw和onDrawOver方法;
1,onDraw方法先於drawChildren
2,onDrawOver在drawChildren之後,一般我們選擇複寫其中一個即可。
3,getItemOffsets 可以通過outRect.set()爲每個Item設置一定的偏移量,主要用於繪製Decorator。
需要自定義 可以參考: Android 自定義RecyclerView 實現真正的Gallery效果
LayoutManager
RecyclerView.LayoutManager, 這是一個抽象類,系統提供了3個實現類;
1,LinearLayoutManager 現行管理器,支持橫向、縱向。
2,GridLayoutManager 網格佈局管理器
3,StaggeredGridLayoutManager 瀑布就式佈局管理器
使用GridLayoutManager , 代碼爲:
//mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setLayoutManager(new GridLayoutManager(this,4));
只需要修改LayoutManager即可
但是改爲GridLayoutManager以後,對於分割線,前面的DividerItemDecoration就不適用了,主要是因爲它在繪製的時候,比如水平線,針對每個child的取值爲:
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
因爲每個Item一行,這樣是沒問題的。而GridLayoutManager時,一行有多個childItem,這樣就多次繪製了,並且GridLayoutManager時,Item如果爲最後一列(則右邊無間隔線)或者爲最後一行(底部無分割線)。
這樣的話需要修改gridview中的分割線item
可以參考: 文章開頭的地址
主要在getItemOffsets方法中,去判斷如果是最後一行,則不需要繪製底部;如果是最後一列,則不需要繪製右邊,整個判斷也考慮到了StaggeredGridLayoutManager的橫向和縱向,所以稍稍有些複雜。最重要還是去理解,如何繪製什麼的不重要。一般如果僅僅是希望有空隙,還是去設置item的margin方便。
StaggeredGridLayoutManager可以有三種用法
使用, StaggeredGridLayoutManager,代碼: StaggeredGridLayoutManager.VERTICAL
// mRecyclerView.setLayoutManager(new GridLayoutManager(this,4));
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
這兩種寫法顯示的效果是一致的,但是注意StaggeredGridLayoutManager構造的第二個參數傳一個orientation,如果傳入的是StaggeredGridLayoutManager.VERTICAL代表有多少列;那麼傳入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行,比如本例如果改爲:StaggeredGridLayoutManager.HORIZONTAL
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.HORIZONTAL));
固定爲4行,變成了左右滑動。有一點需要注意,如果是橫向的時候,item的寬度需要注意去設置,畢竟橫向的寬度沒有約束了,應爲控件可以橫向滾動了。
適用在需要橫向滾動的情況下的listview 或者 gridview
條目動畫 ItemAnimator
item增加、刪除的動畫也是可配置的。
ItemAnimator也是一個抽象類,好在系統爲我們提供了一種默認的實現類
// 設置item動畫
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
PS:這裏更新數據集不是用adapter.notifyDataSetChanged()
而是 notifyItemInserted(position)與notifyItemRemoved(position)
否則沒有動畫效果。
可以爲adapter中添加了兩個方法:
public void addData(int position) {
mDatas.add(position, “Insert One”);
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
}
因爲只有一種動畫, 所以可以去網上搜索一些比較好看的動畫效果
Click and LongClick(點擊事件,,,recyclerview沒有提供,所以需要自己寫)
實現的方式比較多,你可以通過mRecyclerView.addOnItemTouchListener去監聽然後去判斷手勢,
當然你也可以通過adapter中自己去提供回調,這裏我們選擇後者,前者的方式,大家有興趣自己去實現。
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
//...
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;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.tv.setText(mDatas.get(position));
// 如果設置了回調,則設置點擊事件
if (mOnItemClickLitener != null) {
holder.itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
});
holder.itemView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
return false;
}
});
}
}
//...
}
adapter中自己定義了個接口,然後在onBindViewHolder中去爲holder.itemView去設置相應
的監聽最後回調我們設置的監聽。
然後在activity中添加監聽
mAdapter.setOnItemClickLitener(new OnItemClickLitener(){
@Override
public void onItemClick(View view, int position) {
Toast.makeText(HomeActivity.this, position + " click",
Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(HomeActivity.this, position + " long click",
Toast.LENGTH_SHORT).show();
mAdapter.removeData(position);
}
});
}