Recyclerview-的简单用法

来源:互联网 发布:windows nt和windows 8 编辑:程序博客网 时间:2024/06/14 11:32

本篇博客主要讲下面六点:

①RecyclerView与ListView相比它的优点

②RecyclerView的初步用法

③RecyclerView增加分隔线

④RecyclerView的Adapter的用法

⑤RecyclerView的添加和删除方法

⑥给RecyclerView增加条目点击事件


首先介绍一下RecyclerView的优点是什么?

     根据官方的介绍RecylerView是ListView的升级版,既然如此那RecylerView必然有它的优点,现就RecylerView相对于ListView的优点罗列如下:

①RecylerView封装了viewholder的回收复用,也就是说RecylerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的   逻辑被封装了,写起来更加简单。

②提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecylerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还有StaggeredGridLayoutManager等),也就是说RecylerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。你想控制Item的分隔线,可以通过继承RecylerView的ItemDecoration这个类,然后针对自己的业务需求去抒写代码。

③可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecylerView有其自己默认的实现。

先我们用Recyclerview的时候,先导入support-v7包,才可以使用,虽然recyclerview比ListView复杂但这也是RecylerView高度解耦的表现,虽然代码抒写上有点复杂,它的扩展性是极高的。

RecyclerView提供了三种布局管理器:

  • LinerLayoutManager 以垂直或者水平列表方式展示Item
  • GridLayoutManager 以网格方式展示Item
  • StaggeredGridLayoutManager 以瀑布流方式展示Item


我们在线性布局中定义两个Button按键一个添加,一个删除,在定义一个recyclerview控件然后开始执行下面的内容↓

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="yuekao.recycle.MainActivity">    <Button        android:id="@+id/additem"        android:text="添加数据"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="#f0f0"        />    <Button        android:id="@+id/removoitem"        android:text="移除数据"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="#f00"/>    <android.support.v7.widget.RecyclerView        android:id="@+id/rv"        android:divider="#ffff0000"        android:dividerHeight="10dp"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#f0f"        /></LinearLayout>
  下面我们可以分为4个步骤完成:
  1,拿到布局当中的控件,2,给recyclerview设置布局样式,3初始化数据,4最后拿到适配器并绑定

package yuekao.recycle;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener{    private RecyclerView rv;    private List<String> list;    private MyAdaptec adaptec;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //找控件        rv = (RecyclerView) findViewById(R.id.rv);        //添加和删除        findViewById(R.id.additem).setOnClickListener(this);        findViewById(R.id.removoitem).setOnClickListener(this);        //设置样式        rv.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));        //初始化数据        intoDate();        //拿到适配器        adaptec = new MyAdaptec(this, list);        rv.setAdapter(adaptec);        //分割线        rv.addItemDecoration(new DividerGridltemDecoration(this));        //点击事件        adaptec.setOnItemClickLitener(new MyAdaptec.OnItemClickLitener() {            @Override            public void onItemClick(View view, int position) {                Toast.makeText(MainActivity.this, "你点击了"+position, Toast.LENGTH_SHORT).show();            }            @Override            public void onItemLongClick(View view, int position) {                Toast.makeText(MainActivity.this, "长按", Toast.LENGTH_SHORT).show();            }        });    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.additem:                adaptec.add(1);                break;            case R.id.removoitem:                adaptec.removo(1);                break;        }    }    //添加数据    private void intoDate() {        list = new ArrayList<>();        for (int i = 0; i < 100; i++) {            list.add("机器人"+i+"号");        }    }}

当我们给recyclerview设置适配器,这个适配器和listview当中的适配器 差不多一样,不过继承的时候有些不一样,我们可以在自己定义的适配器当中写一些方法比如:点击事件,添加,删除,等等,我们可以来调用这些方法,不过recyclerview的点击事件和listview中的点击事件不一样需要自己写。

RecyclerView中的Item点击事件和Listview中的点击事件是不一样的

 该控件给我们提供一个onItemClickListener监听器,这样当我们点击Item的时候,会回调相关的方法,以便我们方便处理Item点击事件。对于RecyclerView来讲,非常可惜的是,该控件没有给我们提供这样的内置监听器方法,不过我们可以进行改造实现,可以这样实现Item的点击事件的监听,在我们的adapter中增加这两个方法


package yuekao.recycle;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import java.util.List;public class MyAdaptec extends RecyclerView.Adapter<MyAdaptec.MyViewHolder>{    private Context context;    private List<String> list;    private OnItemClickLitener onItemClickLitener;    public MyAdaptec(Context context, List<String> list){        this.context = context;        this.list = list;    }    public void setOnItemClickLitener(OnItemClickLitener onItemClickLitener) {        this.onItemClickLitener = onItemClickLitener;    }    interface OnItemClickLitener {        void onItemClick(View view, int position);        void onItemLongClick(View view, int position);    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = LayoutInflater.from(context).inflate(R.layout.litem,parent,false);        return new MyViewHolder(view);    }    @Override    public void onBindViewHolder(MyViewHolder holder, final int position) {        if (holder instanceof MyViewHolder){            final MyViewHolder myViewHolder = (MyViewHolder) holder;            myViewHolder.text.setText(list.get(position));            if (onItemClickLitener != null){                myViewHolder.text.setOnClickListener(new View.OnClickListener(){                    @Override                    public void onClick(View view) {                        onItemClickLitener.onItemClick(myViewHolder.text,position);                    }                });            }            if (onItemClickLitener != null){                myViewHolder.text.setOnLongClickListener(new View.OnLongClickListener(){                    @Override                    public boolean onLongClick(View view) {                        onItemClickLitener.onItemLongClick(myViewHolder.text, position);                        return true;                    }                });            }        }    }    @Override    public int getItemCount() {        return list.size();    }    //ViewHolder类    public static class MyViewHolder extends RecyclerView.ViewHolder{        private TextView text;        public MyViewHolder(View itemView) {            super(itemView);            text = itemView.findViewById(R.id.jie_tv);        }    }    //添加方法    public void add(int position) {        list.add(position, "新数据");        notifyItemInserted(position);    }    //删除方法    public void removo(int position) {        list.remove(position);        notifyItemRemoved(position);    }}

 这一个类主要是写的是分隔线,我们也可以自己定义一个类里面可以自己设置想要的分隔线的类型

package yuekao.recycle;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.RecyclerView.LayoutManager;import android.support.v7.widget.StaggeredGridLayoutManager;import android.view.View;public class DividerGridltemDecoration extends RecyclerView.ItemDecoration{    private static final int[] ATTRS = new int[] { android.R.attr.listDivider };    private Drawable mDivider;    public DividerGridltemDecoration(Context context)    {        final TypedArray a = context.obtainStyledAttributes(ATTRS);        mDivider = a.getDrawable(0);        a.recycle();    }    @Override    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)    {        drawHorizontal(c, parent);        drawVertical(c, parent);    }    private int getSpanCount(RecyclerView parent)    {        // 列数        int spanCount = -1;        LayoutManager layoutManager = parent.getLayoutManager();        if (layoutManager instanceof GridLayoutManager)        {            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();        } else if (layoutManager instanceof StaggeredGridLayoutManager)        {            spanCount = ((StaggeredGridLayoutManager) layoutManager)                    .getSpanCount();        }        return spanCount;    }    public void drawHorizontal(Canvas c, RecyclerView parent)    {        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.getLeft() - params.leftMargin;            final int right = child.getRight() + params.rightMargin                    + mDivider.getIntrinsicWidth();            final int top = child.getBottom() + params.bottomMargin;            final int bottom = top + mDivider.getIntrinsicHeight();            mDivider.setBounds(left, top, right, bottom);            mDivider.draw(c);        }    }    public void drawVertical(Canvas c, RecyclerView parent)    {        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 top = child.getTop() - params.topMargin;            final int bottom = child.getBottom() + params.bottomMargin;            final int left = child.getRight() + params.rightMargin;            final int right = left + mDivider.getIntrinsicWidth();            mDivider.setBounds(left, top, right, bottom);            mDivider.draw(c);        }    }    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,                                int childCount)    {        LayoutManager layoutManager = parent.getLayoutManager();        if (layoutManager instanceof GridLayoutManager)        {            if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边            {                return true;            }        } else if (layoutManager instanceof StaggeredGridLayoutManager)        {            int orientation = ((StaggeredGridLayoutManager) layoutManager)                    .getOrientation();            if (orientation == StaggeredGridLayoutManager.VERTICAL)            {                if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边                {                    return true;                }            } else            {                childCount = childCount - childCount % spanCount;                if (pos >= childCount)// 如果是最后一列,则不需要绘制右边                    return true;            }        }        return false;    }    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,                              int childCount)    {        LayoutManager layoutManager = parent.getLayoutManager();        if (layoutManager instanceof GridLayoutManager)        {            childCount = childCount - childCount % spanCount;            if (pos >= childCount)// 如果是最后一行,则不需要绘制底部                return true;        } else if (layoutManager instanceof StaggeredGridLayoutManager)        {            int orientation = ((StaggeredGridLayoutManager) layoutManager)                    .getOrientation();            // StaggeredGridLayoutManager 且纵向滚动            if (orientation == StaggeredGridLayoutManager.VERTICAL)            {                childCount = childCount - childCount % spanCount;                // 如果是最后一行,则不需要绘制底部                if (pos >= childCount)                    return true;            } else            // StaggeredGridLayoutManager 且横向滚动            {                // 如果是最后一行,则不需要绘制底部                if ((pos + 1) % spanCount == 0)                {                    return true;                }            }        }        return false;    }    @Override    public void getItemOffsets(Rect outRect, int itemPosition,                               RecyclerView parent)    {        int spanCount = getSpanCount(parent);        int childCount = parent.getAdapter().getItemCount();        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部        {            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边        {            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());        } else        {            outRect.set(0, 0, mDivider.getIntrinsicWidth(),                    mDivider.getIntrinsicHeight());        }    }}

这个就是litem的布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content">    <ImageView        android:src="@mipmap/ic_launcher"        android:layout_width="80dp"        android:layout_height="80dp" />    <TextView        android:id="@+id/jie_tv"        android:gravity="center"        android:layout_width="match_parent"        android:layout_height="80dp" /></LinearLayout>