RecycleView简单介绍

通过此文可以简单了解以下:

  • 1、RecycleView是什么
  • 2、RecycleView的简单使用
  • 3、RecycleView Item分割线的自定义
  • 4、RecycleView的默认动画
    先来看下效果:
    RecycleView简单介绍_第1张图片

RecycleView已经面世很久,相信大家也已经有所熟悉,也在很多应用中得到广泛的使用。那么RecyclerView拥有比ListView,GridView之类控件都有哪些优点呢:

  • 1、数据绑定
  • 2、Item View创建
  • 3、View的回收以及重用等机制。

RecycleView的简单介绍:
有关recycleview的介绍,网上已经有了好多,在次小白理解尚浅,就不过多介绍了

①.采用LayoutManager来处理Item的布局
②.提供Item操作的默认动画,例如在增加或者删除item的时候
你也可以自定义LayoutManager或者设置添加/删除的动画,整体的RecyclerView结构图如下:
RecycleView简单介绍_第2张图片

RecyclerView提供了三种内置的LayoutManager:

    * LinearLayoutManager:线性布局,横向或者纵向滑动列表
      线性布局,类型包括Vertical和Horizontal
  • GridLayoutManager:表格布局,继承自LinearLayoutManager,实现效果类似GridView

    *  StaggeredGridLayoutManager:流式布局,例如瀑布流效果交错的格子布局,同样也是LayoutManager的实现类,类型包括Vertical和Horizontal,与GridLayoutManager很相似,不过是交错的格子,也就是宽高不等的格子视图,类似瀑布流的效果
    

RecycleView的相关类:
RecycleView简单介绍_第3张图片

RecycleView的基本用法:

  • 1、添加依赖 compile 'com.android.support:design:23.1.1'(这个包下也有) 或者 compile'com.android.support:recyclerview-v7:23.1.1’
  • 2、使用recycleview组件,和listview使用一样。
  • 3、控件初始化,设置布局管理器以及Adapter

好了,下面我们就来使用代码说明一下怎么使用吧:

1、RecycleView的适配器Adapter:适配器,绑定数据集

继承 RecyclerView.Adapter
要重写的方法

// 创建ViewHolder ,相当于ListVie Adapter 的getView 方法
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {    
      return null;
}
// 数据绑定
public void onBindViewHolder(ViewHolder viewHolder, int i) {}

// 数据的长度
public int getItemCount() {    return 0;}

2、ViewHolder:根据当前的数据保存视图

继承 RecyclerView.ViewHolder
要重写的方法

class ViewHolder extends RecyclerView.ViewHolder{        
    public ViewHolder(View itemView) {       
       super(itemView);                
       // 绑定控件   
      }
 }

3、ItemDecoration:勉强理解为item装饰器,可以美化item

1.继承 RecyclerView.ItemDecoration
2. 重要方法:
//在itemView绘制完成之前调用,也就是说此方法draw出来的效果将会在itemView的下面
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) 
{    
    super.onDraw(c, parent, state);
}

//与onDraw相反,draw出来的效果将叠加在itemView的上面
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) 
{    
    super.onDrawOver(c, parent, state);
}

//算通过配置outRect来设置itemView的inset边界,相当于设置itemView的margin
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
   super.getItemOffsets(outRect, view, parent, state);
   }

4、ItemAnimator:动画(当item被增加,删除,重新摆放时动画才有效)。

1.继承 RecyclerView.ItemAnimator

2. 提供默认的Animator:DefaultItemAnimator

3.github 开源

https://github.com/gabrielemariotti/RecyclerViewItemAnimators

5、LayoutManager:布局管理器。决定item如何摆放

LinearLayoutManager 
线性布局,LayoutManager的实现类,类型包括VerticalHorizontal

GridLayoutManager
格子布局,继承自LinearLayoutManager,实现效果类似GridView

StaggeredGridLayoutManager
交错的格子布局,同样也是LayoutManager的实现类,类型包括VerticalHorizontal,与GridLayoutManager很相似,不过是交错的格子,也就是宽高不等的格子视图,类似瀑布流的效果

来看下代码怎么实现的吧,代码里面的解释一般都有了:

MainActivity.java

package com.example.recycleviewdemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    /**
     * 数据集合
     */
    private List mDatas;

    //控件
    private RecyclerView mRecyclerView;

    //适配器
    private MyAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDatas = new ArrayList<>();
        ininViews();
        initData();
        initAdapter();
    }

    //初始化布局控件
    private void ininViews() {
        mRecyclerView = (RecyclerView) findViewById(R.id.recycleview);
    }


    private void initAdapter() {
        //初始化adapter
        mAdapter = new MyAdapter(mDatas);
        /**
         * Support库提供了两个现成的子类:LinearLayoutManager和StaggeredGridLayoutManager。
         * 前者可以获得和ListView一样的布局,还可以是水平方向的;后者则提供了形如GridView的布局。
         */
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
        //设置adapter
        mRecyclerView.setAdapter(mAdapter);
        //画横线
        mRecyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));

        //默认动画   貌似官方就提供了这一种默认的动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

        /**
         * 在这我们就能实现item的点击事件了
         */
        mAdapter.setListener(new MyAdapter.OnItemClickListener() {
            @Override
            public void onClick(View v, int position, String str) {
                Toast.makeText(MainActivity.this, "点击我干嘛啊,真是没事找事", Toast.LENGTH_SHORT).show();
            }
        });

    }

    /**
     * 添加事件
     *
     * @param view
     */
    public void btnAdd(View view){
        mAdapter.addData("小红", 3);
    }

    /**
     * 删除事件
     *
     * @param view
     */
    public void btnDelete(View view){
        mAdapter.remove(4);
    }

    /**
     * 初始化集合数据
     */
    private void initData() {
        mDatas.add("New York");
        mDatas.add("Bei Jing");
        mDatas.add("Boston");
        mDatas.add("London");
        mDatas.add("San Francisco");
        mDatas.add("Chicago");
        mDatas.add("Shang Hai");
        mDatas.add("Tian Jin");
        mDatas.add("Zheng Zhou");
        mDatas.add("Hang Zhou");
        mDatas.add("Guang Zhou");
        mDatas.add("Fu Gou");
        mDatas.add("Zhou Kou");
    }

}

MyAdapter.java:

package com.example.recycleviewdemo;

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;

/**
 * Created by 若兰 on 2016/1/27.
 * 一个懂得了编程乐趣的小白,希望自己
 * 能够在这个道路上走的很远,也希望自己学习到的
 * 知识可以帮助更多的人,分享就是学习的一种乐趣
 * QQ:1069584784
 * csdn:http://blog.csdn.net/wuyinlei
 */

/**
 * Adapters provide a binding from an app-specific data
 * set to views that are displayed within a RecyclerView.
 */
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {


    private LayoutInflater mInflater;

    private List mLists;

    private OnItemClickListener mListener;

    public void setListener(OnItemClickListener listener) {
        mListener = listener;
    }

    public MyAdapter(List lists) {
        mLists = lists;
    }

    //创建布局
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        mInflater = LayoutInflater.from(parent.getContext());
        //加载布局
        View view = mInflater.inflate(R.layout.item_recycle, null);
        //返回viewholder
        return new MyViewHolder(view);
    }


    /**
     * 在指定的位置添加数据
     *
     * @param data
     * @param position
     */
    public void addData(String data, int position) {
        mLists.add(data);
        //通知布局在那个地方插入的数据
        notifyItemInserted(position);
    }

    /**
     * 移除特定的位置的数据
     *
     * @param position 索引位置
     */
    public void remove(int position) {
        mLists.remove(position);
        notifyItemRemoved(position);
    }

    public void addData(List datas) {
        mLists.addAll(datas);
        //通知添加数据,第一个位置 数据的数量
        notifyItemRangeChanged(0, datas.size());
    }

    //绑定布局
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.mTextView.setText(mLists.get(position));
    }

    //获取到item的个数
    @Override
    public int getItemCount() {
        return mLists.size();
    }


    // 强制使用ViewHolder

    /**
     * 在ListView性能优化方面,Android就推荐使用ViewHolder来减少findViewById()的使用以提高效率。
     * 不过对于ListView上的ViewHolder,Android只是建议而非强制使用。不过因为使用ViewHolder
     * 模式太有意义了,所以在RecyclerView中ViewHolder就变成了必须使用的模式,Adapter要求返回的也
     * 从普通的View变成了ViewHolder。
     * 不过如果实现时没有自定义的一些View实际变量,ViewHolder也依然失去其意义。
     */
    class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView mTextView;

        public MyViewHolder(View itemView) {
            super(itemView);
            if (itemView != null) {
                mTextView = (TextView) itemView.findViewById(R.id.textview);
                mTextView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mListener != null) {
                            /**
                             * getLayoutPosition()  返回的是item的当前点击的位置
                             * Returns the position of the ViewHolder in terms of the latest layout pass.
                             */
                            mListener.onClick(v, getLayoutPosition(), mLists.get(getLayoutPosition()));
                        }
                    }
                });
            }

        }
    }

    /**
     * 没有OnItemClickListener
     * 必须我们自己去实现
     */
    interface OnItemClickListener {
        void onClick(View v, int position, String str);
    }
}

DividerItemDecoration.java:(绘制item之间的直线的,本身没有提供,要自己写)

package com.example.recycleviewdemo;

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.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by 若兰 on 2016/1/26.
 * 一个懂得了编程乐趣的小白,希望自己
 * 能够在这个道路上走的很远,也希望自己学习到的
 * 知识可以帮助更多的人,分享就是学习的一种乐趣
 * QQ:1069584784
 * csdn:http://blog.csdn.net/wuyinlei
 */

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    /**
     * 采用系统的内置的分割线风格
     */
    private static final int[] attrs = new int[]{android.R.attr.listDivider};
    private final TypedArray mTypedArray;


    //水平方式
    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) {
        super();
        //读取系统自定义属性
       // Returns a TypedArray holding an array of the attribute values.
        mTypedArray = context.obtainStyledAttributes(attrs);
        mDivider = mTypedArray.getDrawable(0);

        //回收资源
        mTypedArray.recycle();
        setHorizontal(orientation);
    }

    /**
     * 判断传入的是横向的还是纵向的
     *
     * @param orientation
     */
    private void setHorizontal(int orientation) {
        //如果两种都不是就抛出异常
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("错误的方式");
        }
        mOrientation = orientation;
    }


    //left  top right bottom

    /**
     * 绘制   根据传入的是水平的还是垂直的
     *
     * @param c
     * @param parent
     * @param state
     */
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
    }

    /**
     * linear  垂直列表
     *
     * @param c
     * @param parent
     */
    private void drawVertical(Canvas c, RecyclerView parent) {
        int left = parent.getPaddingLeft();

        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            //得到布局中的子item
            View childView = parent.getChildAt(i);

            //得到子view的布局泵  LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息
            RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) childView.getLayoutParams();
            /**
             * top 是子view的底布局加上和他的底margin值
             */
            int top = childView.getBottom() + layoutParams.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();
            //设置四个方向的bounds
            mDivider.setBounds(left, top, right, bottom);
            //然后画线
            mDivider.draw(c);
        }
    }

    /**
     * 横向列表的横线
     *
     * @param c
     * @param parent
     */
    private 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);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

activity_main.xml:


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
   >
<LinearLayout
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="wrap_content">
    <Button
        android:layout_weight="1"
        android:onClick="btnAdd"
        android:text="添加"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:text="删除"
        android:onClick="btnDelete"
        android:layout_weight="1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycleview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    android.support.v7.widget.RecyclerView>
LinearLayout>

item_recycle.xml:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <TextView
        android:id="@+id/textview"
        android:gravity="center"
        android:text="hello"
        android:textSize="20dp"
        android:padding="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
RelativeLayout>

好了,基本上这些应该可以满足工作中的的一般事情了,(或许是我自大了哈),RecycleView的知识好多呢,这个要想了解一手的资料,建议还是去官方去看下。
如果有兴趣可以看下我的另一篇文章,RecycleView+SwipeRefreshLayout实现下拉刷新和 RecycleView+MaterialRefreshLayout实现下拉刷新和上拉加载更多。希望有所帮助
RecycleView + SwipeRefreshLayout 实现下拉刷新:

  • http://blog.csdn.net/wuyinlei/article/details/49805567

MaterialRefreshLayout实现下拉刷新上拉加载更多:

  • http://blog.csdn.net/wuyinlei/article/details/50586548

你可能感兴趣的:(android开发,学习心得,项目实战之总结篇)