初探RecyclerView开发

很长时间没有从事android项目开发了,最近一直在看android新的知识,android开发中列表是非常常见的,以前LIstView效果比较单一,扩展多了会影响性能,现在比较火的RecyclerVIew引起了我的兴趣,决定学习一下。很久没写博客了,顺便记录下,以便回顾。

1,RecyclerView简介

RecyclerView是从android5.0版本开始推出的,依赖于support-v7的一款新的组件,功能强大,不仅可以实现原来ListView的线性列表的效果,还可以实现GridView的网格列表效果以及瀑布流的效果,可以分别通过LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager来管理横向或者竖向的滑动效果。通过自定义继承ItemDecoration类来实现分割线的绘制和效果。Adapter里面封装了复用逻辑,返回的是ViewHolder,不是View。另外还添加了可以控制item增删的动态动画效果。

2,入门实践

废话不多说,开始实践。

1)布局

理所当然,打开布局文件,先布局一个RecyclerView控件进去(这里有部分童鞋会发现怎么自动补全里面没有RecyclerView,或者打上去报错,解决方法:在app目录下面的build.gradle文件里面,在“compile 'com.android.support:appcompat-v7:xx.x.x'”下面加一行代码“compile 'com.android.support:recyclerview-v7:xx.x.x'”,然后clean一下project,这个时候就有RecyclerView控件了),设置好宽高铺满。

2)查找组件

在Activity中查找组件,设置属性:

//查找控件
        recyclerview = (RecyclerView) findViewById(R.id.recyclerview);
        //创建设置布局管理器
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerview.setLayoutManager(layoutManager);

LinearLayoutManager设置是横向还是竖向滑动。

3)自定义适配器

自定义适配器,需要继承Adapter类,面向ViewHolder,但是需要自己定义ViewHolder类。

同时需要实现三个方法:

getItemCount()

这个方法就是返回获得数据的数目。

onCreateViewHolder()

生成每个item的view,封装到ViewHolder里面去,返回ViewHolder。

onBindViewHolder()

适配数据到view中去。

贴上代码:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

    private Context mContext;
    private List<String> data;

    public RecyclerAdapter(Context context, List<String> d){
        mContext = context;
        data = d;
    }


    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(mContext).inflate(R.layout.item_lay,parent,false);
        MyViewHolder vh = new MyViewHolder(view);

        return vh;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        holder.tv.setText(data.get(position).toString());
        
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        public TextView tv;

        public MyViewHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }
    }

}
顺便附上item布局的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="50dp"
>

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textSize="20sp"
            android:textColor="#ffffff"
            android:background="#999999" />


</LinearLayout>

此时需要在Activity中实例化适配器,绑定适配器到REcyclerView了:

private RecyclerAdapter adapter;
//绑定适配器
        adapter = new RecyclerAdapter(this,mData);
在这之前记得初始化添加数据集:

 private List<String> mData;
mData = new ArrayList<String>();
        for(int i = 0;i < 20;i++){
            mData.add("第"+i+"行");
        }

此时运行,就会看到无分割线的列表。

4)自定义分割线

RecyclerView的分割线不像ListView的分割线那样直接配置属性就好了,这里稍微繁琐一点,需要自定义继承ItemDecoration类。

主要要重写三个方法:getItemOffsets(),还有onDraw()和onDrawOver两者其中之一就可以了。

getItemOffsets()

从字面意思就是Item要偏移, 由于我们在Item和Item之间加入了分隔线,线其实本质就是一个长方形,也是用户自定义的,既然线也有长宽高,就画横线来说,上面的Item加入了分隔线,那下面的Item就要往下平移,平移的量就是分隔线的高度。

这里面重要的是要拿到画分割线的坐标,也就是left,top,right,bottom的值。

首先讲一下忽略item布局里面设置的margin,padding属性,来获取坐标值。

a)竖向的列表,即横向绘制分割线

left:0

right:parent.getWidth()

top:每个item的底部,就是下面的分割线的top,可以通过childView.getBottom()来获取到。

bottom:就是top+想绘制的分割线的高度。

b)横向列表,即竖向绘制分割线

top:0

bottom:parent.getHeight()

left:每个item的右边,就是后面分割线的left,可以通过childView.getRight()来获取到

right:就是left+分割线的宽度

再来讲下考虑padding,margin属性的获取方法

a)竖向的列表,即横向绘制分割线

left:0+parent.getPaddingLeft()

right:parent.getWidth() - parent.getPaddingRight

top:每个item的底部+底部margin的值,就是下面的分割线的top,可以通过childView.getBottom()来获取到,再加上view的LayoutParams调用bottomMargin

bottom:就是top+想绘制的分割线的高度。

b)横向列表,即竖向绘制分割线

top:0+parent.getPaddingTop()

bottom:parent.getHeight() - parent.getPaddingBottom()

left:每个item的右边+右边的margin,就是后面分割线的left,可以通过childView.getRight()来获取到,再加上view的LayoutParams调用rightMargin

right:就是left+分割线的宽度

直接上代码:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private Context mContext;
    private Drawable divider;
    private int mOrientation;
    private static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    private static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    public static final int [] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public DividerItemDecoration(Context context,int orientation){
        super();
        mContext = context;
        mOrientation = orientation;
        TypedArray ta = context.obtainStyledAttributes(ATTRS);
        this.divider = ta.getDrawable(0);
        ta.recycle();
        setOrientation(orientation);
    }

    //设置屏幕方向
    private void setOrientation(int orientation){
        if(orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
            throw new IllegalArgumentException("invalid orientation");
        }
    }

    //画横线
    public void drawHorizontalLine(Canvas c, RecyclerView parent,RecyclerView.State state){
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();
        int count = parent.getChildCount();
        for(int i = 0;i < count;i++){
            View view = parent.getChildAt(i);
            //获取childView的布局信息
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
            int top = view.getBottom() + params.bottomMargin;
            int bottom = top+divider.getIntrinsicHeight();
            divider.setBounds(left,top,right,bottom);
            divider.draw(c);
        }
    }

    //画竖线
    public void drawVerticalLine(Canvas c, RecyclerView parent,RecyclerView.State state){
        int top = parent.getPaddingTop();
        int bottom = parent.getHeight() - parent.getPaddingBottom();
        int count = parent.getChildCount();
        for(int i = 0;i < count;i++){
            View view = parent.getChildAt(i);
            //获取childview布局信息
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
            int left = view.getRight() + params.rightMargin;
            int right = left + divider.getIntrinsicWidth();
            divider.setBounds(left,top,right,bottom);
            divider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if(mOrientation == HORIZONTAL_LIST){
            //画横线,就是往下偏移一个分割线的高度
            outRect.set(0, 0, 0, divider.getIntrinsicHeight());
        }else {
            //画竖线,就是往右偏移一个分割线的宽度
            outRect.set(0, 0, divider.getIntrinsicWidth(), 0);
        }
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        if(mOrientation == VERTICAL_LIST){
            drawHorizontalLine(c,parent,state);
        }else{
            drawVerticalLine(c,parent,state);
        }
    }
}

附上分割线代码:

drawable:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#7b7a7a"/>
    <size android:height="1dp"/>
</shape>

在AppTheme下添加

<item name="android:listDivider">@drawable/divider</item>
然后在Activity中给RecyclerVIew添加分割线:

//添加自定义分割线
        recyclerview.addItemDecoration(new DividerItemDecoration(this,LinearLayoutManager.VERTICAL));


此时运行,就会发现item下面有华丽丽的分割线了。


5)实现item点击事件

RecyclerView不像ListView有onItemClickListener事件,这里需要自己在Adapter中添加点击事件的监听。

//item回调接口
    public interface OnItemClickListener{
        void OnItemClick(View view,int position);
    }
创建一个对外开放的事件调用:

//开放的点击监听器的方法
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        mOnItemClickListener = onItemClickListener;
    }

不多说了,再上一次Adapter的代码。
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

    private Context mContext;
    private List<String> data;
    private OnItemClickListener mOnItemClickListener;

    public RecyclerAdapter(Context context, List<String> d){
        mContext = context;
        data = d;
    }

    //item回调接口
    public interface OnItemClickListener{
        void OnItemClick(View view,int position);
    }

    //开放的点击监听器的方法
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        mOnItemClickListener = onItemClickListener;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(mContext).inflate(R.layout.item_lay,parent,false);
        MyViewHolder vh = new MyViewHolder(view);

        return vh;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        holder.tv.setText(data.get(position).toString());
        if(mOnItemClickListener != null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mOnItemClickListener.OnItemClick(holder.itemView,position);
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        public TextView tv;

        public MyViewHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }
    }

}

在Activity中添加:

adapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() {
            @Override
            public void OnItemClick(View view, int position) {
                Toast.makeText(MainActivity.this,"点击了"+position,Toast.LENGTH_SHORT).show();
            }
        });


源码地址:http://download.csdn.net/detail/liujibin1836591303/9705656

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值