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);
            }
        });
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值