RecycleView學習

這是之前保存的學習筆記, 現在上傳保存一下

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);
    }
}

因爲只有一種動畫, 所以可以去網上搜索一些比較好看的動畫效果

RecyclerView的一些動畫效果

一個比較好的動畫的library

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);
            }
        });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章