RecyclerView新体验(1)

在群里经常听到有人在讨论到RecyclerView,说的神乎其神,还有人说用了RecyclerView之后都不想用ListView了,是不是有那么神奇呢?做为一个最菜的小菜鸟也要去了解下才好。

关于RecyclerView

RecyclerView 和CardView等都是Android 5.0版本中新添加的控件,RecyclerView 是一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好。很多人都认为,RecyclerView是ListView、GridView的升级版,不仅具有了ListView和GridView的功能,还用很简单的方法实现了瀑布流。但是RecyclerView作为新的控件,与ListView和GridView有着很大的区别,有着自己的特性:
RecyclerView只负责如何回收和复用Item,其他的都交给相应的管理器去负责,如Item的显示交给布局管理器LayoutManager负责处理;将Item之间的间隔交由ItemDecoration负责;动画效果交给ItemAnimator负责处理。

如何使用RecyclerView

1.添加依赖

在AS的build.gradle中添加依赖,然后同步一下就好:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:recyclerview-v7:23.1.0'
}
2.编写xml文件
<RelativeLayout 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.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_below="@+id/tv_com"
        android:layout_width="match_parent"
        android:dividerHeight="4dp"
        android:layout_height="match_parent"/>
</RelativeLayout>

顺便写一个简单item布局文件,只是测试而已,非常简单

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#f1f1f1"
    >
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="10dp"
        android:gravity="center"
        android:textColor="#646464"
        android:textSize="18sp" />
</RelativeLayout>
3.类似ListView一样,我们同样也需要写一个Adapter,值得注意的是RecyclerView的Adapter不是继承BaseAdapter,而是继承了RecyclerView.Adapter< VH>并且通过一个泛型参数强制要求使用ViewHolder。因此我们的Adapter如下:
public class CommonRecyclerViewAdapter extends RecyclerView.Adapter<CommonRecyclerViewAdapter.MyViewHolder> {
    private Context context;
    private List<String> list;

    public CommonRecyclerViewAdapter(Context context, List<String> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    //绑定item布局
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_rcv,null));
    }
//进行view和数据源的绑定
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tv.setText(list.get(position));
    }
//返回数据的总条目数量
    @Override
    public int getItemCount() {
        return list.size();
    }
//ViewHolder
    public class MyViewHolder extends RecyclerView.ViewHolder{

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

简单的适配器就这样完成了,下面只要我们的activity和Adapter关联起来就完成了。

4.在Activity中与Adapter绑定实现ListView功能。
public class CommonRecyclerViewActivity extends Activity implements View.OnClickListener {
    private RecyclerView rv;
    private List<String> list;
    private Activity activity;
    private CommonRecyclerViewAdapter adapter;

    int position=0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_common_recycler_view);
        initData();
        rv = (RecyclerView) findViewById(R.id.rv);

        //RecyclerView布局管理器设置
        /**
         * LinearLayoutManager 线性管理器,支持横向、纵向。
         GridLayoutManager 网格布局管理器
         StaggeredGridLayoutManager 瀑布就式布局管理器
         */

        //listview
        rv.setLayoutManager(new LinearLayoutManager(this));
        //设置Adapter
        adapter = new CommonRecyclerViewAdapter(this,list);
        rv.setAdapter(adapter);
    }
private void initData() {
        list = new ArrayList<>();
        for (int i = 0; i < 101; i++) {
            list.add("RecyclerView Item "+i+"   000000000");
        }
    }

看,一个简单的listview的效果出来了,请忽视界面的丑陋,现在只是做一个功能性的演示而已。
这里写图片描述

5.GridView效果

单单从这里也看不出来RecyclerView比ListView有多大的优势,但是如果我们要切换到GridView的样式中就简单多,前面1-3相关代码均不需要做什么改动,只要改变4Activity中的布局管理器代码就好

//其他代码不变,只需改变布局管理器就好
//rv.setLayoutManager(new LinearLayoutManager(this));
//表示4列的GridView
rv.setLayoutManager(new GridLayoutManager(this,4));

下面我们来看下效果

这里写图片描述

效果是达到了,尼玛的,没有分割线就是丑,下次一定要把分割线搞出来。
上面只是很常规的ListView和GridView效果,我们还能利用RecyclerView做横向滑动的ListView和GridView效果,做起来也简单,还是只改变管理器的布局代码就好。
横向的GridView和ListView

//横向滑动的4列GridView,如果要横向滑动的ListView是不是也很简单呢?是的,只需将横向的列数设置为1就好。
rv.setLayoutManager(new GridLayoutManager(this,4,GridLayoutManager.HORIZONTAL,false));
6.完美的瀑布流

实现的上面的功能我们已经开始有一点点佩服RecyclerView了,但是他还有一个功能就是完美地实现了瀑布流的布局。
我们需要变化的是两个地方,一个是Adapter,通过Adapter控制瀑布流的大小,具体代码如下;

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

    private Context context;
    private List<String> list;
    private int[] num = {1,2,3,2,2,6};

    public StaggeredRecyclerViewAdapter(Context context, List<String> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_rcv, null));
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();

        //设置不同大小的布局
        lp.height = 600/num[position%num.length];

        holder.tv.setLayoutParams(lp);
        holder.tv.setText(list.get(position));
        //设置不同的颜色便于区分
        if (position % 3 == 0)
            holder.layout.setBackgroundColor(Color.GREEN);
        else if (position % 3 == 1)
            holder.layout.setBackgroundColor(Color.RED);
        else
            holder.layout.setBackgroundColor(Color.BLUE);
    }

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

    public class MyViewHolder extends RecyclerView.ViewHolder {

        TextView tv;
        RelativeLayout layout;

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

然后在Activity中简单地改变下布局管理器

rv.setAdapter(new StaggeredRecyclerViewAdapter(this,list));
        rv.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));

看,完美的瀑布流出来了:

这里写图片描述

到此,最简单的RecyclerView的应用已经差不多了,之前上面说到没有分割线看起来不怎么好看,所以在网上看了下关于分割线的资料。系统给我们提供了一个关于分割线的抽象类(ItemDecoration.java),但是没有给出任何一个实现类。我在网上找到了一个关于RecyclerView分割线的实现类,还不错,网上很多地方都看见有,至于真正的作者是谁就不知道了。附上源码以供学习:

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

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

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

//在子view绘制之前绘制,一般来说onDraw和onDrawOver只需复写其中一个就好
    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
        Log.v("recyclerview - itemdecoration", "onDraw()");

        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        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 left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
    //在子view绘制完成后绘制
    public void onDrawOver(Canvas c, RecyclerView parent, State state) {
            onDrawOver(c, parent);
 }
//可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator
    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}
7.RecyclerView中添加分割线
//只要在设置布局管理器的时候设置即可
rv.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));

对于RecyclerView的简单的学习先到这里,如有错误,欢迎提出并指正。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值