您的位置:首页 > 其它

RecycleView的基础使用

2016-04-19 22:17 204 查看
RecycleView
5.0之后的新控件
作用:用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView

可以实现ListView,GridView的效果
可以瀑布流效果
可以方便列表多布局效果
再删除或者增加条目时,支持动画效果
自带View复用效果
使用方式:
控制显示方式

给当前工程添加com.android.support.recyclerview-v7类库

(导入外部library包,
 包名为:com.android.support:recyclerview-v7:23.1.0在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径)

在代码中获取控件对象
设置布局管理器
LinearLayoutManager    线性布局管理器,支持横向,纵向
GridLayoutManager    网格布局管理器
StaggeredGridLayoutManager    瀑布流式布局管理器 

此处设置布局管理器的目的在于:由于RecyclerView控件可以实现ListView,GridVIew等多种效果,因此需要通过布局管理器来通知RecyclerView要显示的是ListView效果还是GridView等效果

设置适配器
适配器要使用RecyclerView.Adapter的子类
在适配器的子类中创建RecyclerView类库中的ViewHolder的子类,并将创建适配器子类时设置的泛型设置为当前ViewHolder子类的类型

在ViewHolder子类的构造方法中初始化控件
按要求重写适配器中的方法
nCreateViewHolder:用于初始化ViewHolder子类对象
onBindViewHolder:用于设置ViewHolder子类中控件的显示内容
getItemCount  :用于决定RecyclerView中总共要显示多少个条目

控制Item间的间隔线

将路径:sdk\extras\android\support\samples\Support7Demos\src\com\example\android\supportv7\widget\decorator 中的DividerItemDecoration类拷贝到本工程中
通过addItemDecoration方法设置DividerItemDecoration对象即可添加间隔线
如需要自定义间隔线:
在drawable文件夹中通过shape绘制任意形状
在AppTheme样式中添加:               <itemname="android:listDivider">@drawable/divider_bg</item>

GridLayoutManager  的用法

通过构造方法初始化对象
通过setLayoutManager方法设置此对象即可

StaggeredGridLayoutManager 的用法

通过构造方法初始化对象
通过setLayoutManager方法设置此对象即可

注:如果要实现瀑布流效果,只需在适配器子类的onBindViewHolder给控件提供随机高度即可

控制点击、长按事件

通过在adapter中添加接口回调手动实现
在onBindViewHolder方法中通过holder.itemView 获取当前item显示的View对象
在监听事件重写方法中通过holder.getLayoutPosition方法获取点击的item所在的position位置

控制Item增删的动画

默认情况下自带动画
或者可以通过setItemAnimator方法设置自定义动画,
也可参考github上的RecyclerViewItemAnimators工程的动画效果

适配器创建的步骤:
创建一个RecyclerView.Adapter的子类,
在该子类内部创建一个RecyclerView.ViewHolder的子类,在该类的构造方法中,处理每行的item中的控件的初始化
将适配器子类声明时的泛型修改为第2步中ViewHolder子类类型
重写适配器子类中的方法
 
/*
* 创建Adapter适配器子类,
* 泛型的作用:
* 限制每行的item要显示的ViewHolder的类型
* */
class MyFirstAdapter extends RecyclerView.Adapter<MyFirstAdapter.MyViewHolder>{

    //当初始化MyViewHolder对象时运行
    /*
    * 运行特点为:
    * 当初始显示时,通过此方法+onBindViewHolder方法控制每一行的显示
    * 但是一旦开始滑动,系统判断可以重用时,不再运行此方法,
    * 只运行onBindViewHolder方法控制显示
    * 返回值:
    * 控制item中控件显示的MyViewHolder对象
    *
    * 参数一:recyclerview对象
    * */
    @Override
    public MyViewHolder
onCreateViewHolder(ViewGroup parent, int viewType)
{
        Log.i("====","======
  onCreateViewholder");
        return new MyViewHolder(LayoutInflater.from(ReListActivity.this)
                                .inflate(R.layout.item,parent,false));
    }

    //用于填充每一个item中的显示内容
    //即设置holder对象中的每一个控件要显示什么样的内容
    //参数二:当前的行的position位置
    @Override
    public
void onBindViewHolder(MyViewHolder holder, int position)
{
        Log.i("====","======
  onBindViewHolder  "+position);
        holder.tv.setText(list.get(position));
    }
    //通过返回值控制列表中总共要显示多少个条目
    @Override
    public
int getItemCount() {
        return list.size();
    }

    /*
            * 创建一个ViewHolder的子类
            * 用于初始化item中控件对象
            * */
    class MyViewHolder extends RecyclerView.ViewHolder
{

        public TextView tv;
        public ImageView iv;
        //参数:列表中显示的item中的View对象
        public MyViewHolder(View
itemView) {
            super(itemView);
            tv =
(TextView)itemView.findViewById(R.id.textView);
            iv =
(ImageView)itemView.findViewById(R.id.imageView);
        }
    }
}
 
注:RecyclerView的Adapter适配器自带复用效果。
当初始显示时,通过onCreateView方法和onBindViewHolder方法控制item的显示
当可以复用时,直接调用onBindViewHolder复用之前创建的holder对象
 
简单来说:onCreateView方法用于处理ViewHolder对象的创建,指定item中要显示哪个ViewHolder对象,每个item中显示哪些控件
 
onBindViewHolder方法 控制的是item中的每个控件上要显示什么样的数据
设置RecyclerView的Item的点击事件
RecyclerView中并不存在显示的item点击的监听事件,因此想要获取item的点击事件及获取被点击的item的position时,
添加点击事件的方式为:
/*
* holder.itemView 代表的是item显示的View对象
* */
holder.itemView.setOnClickListener(new View.OnClickListener()
{
    @Override
    public
void onClick(View v) {
        //如果Adapter是外部类,那么此处的点击事件需要通过接口回调的方式传回给Activity
        Toast.makeText(ReListActivity.this, "当前被点击的位置为"+holder.getLayoutPosition(),
Toast.LENGTH_SHORT).show();
    }
});
 

实现列表多布局
 
如实现:

*  0-4  显示的是一个TextView

*  5-10  显示的是一个ImageView+一个TextView

*  11-15 显示的是四个Imageview
 
关键是针对适配器子类的处理:
 
class MyDuoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

    @Override
    public RecyclerView.ViewHolder
onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder holder = null ;
       //根据不同的viewType类型初始化不同的ViewHolder对象
        switch (viewType)
{
            case 0:
                holder = new MyDuoHolder1(LayoutInflater.from(DuoLayoutActivity.this).inflate(R.layout.duo1,parent,false));
                break;
            case 1:
                holder = new MyDuoHolder2(LayoutInflater.from(DuoLayoutActivity.this).inflate(R.layout.duo2,parent,false));
                break;
            case 2:
                holder = new MyDuoHolder3(LayoutInflater.from(DuoLayoutActivity.this).inflate(R.layout.duo3,parent,false));
                break;
            }

        return holder;
    }
    //该方法在onCreateViewHolder之后运行,并且接收onCreateViewHolder方法的返回值作为参数1
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder
holder, int position) {

        //判断当前返回的holder属性的那种ViewHoder的子类
        //根据不同的种类,设置其中控件数据的显示
        if (holder instanceof MyDuoHolder1)
{
            MyDuoHolder1 md1 = (MyDuoHolder1) holder;
            md1.duo1_tv.setText(list.get(position));
        } else if (holder instanceof
 MyDuoHolder2) {
            MyDuoHolder2 md2 = (MyDuoHolder2) holder;
            md2.duo2_tv.setText(list.get(position));
            //再取出图片数据时注意:要根据当前position-duo1布局中所显示的数据个数才可以
            //否则会造成下标越界
            md2.duo2_iv.setImageResource(imgs[position-5]);
        } else if (holder instanceof MyDuoHolder3)
{
            MyDuoHolder3 md3 = (MyDuoHolder3) holder;
            md3.duo3_iv1.setImageResource(imgs[0]);
            md3.duo3_iv2.setImageResource(imgs[1]);
            md3.duo3_iv3.setImageResource(imgs[2]);
            md3.duo3_iv4.setImageResource(imgs[3]);

        }
    }

    @Override
    public int getItemCount()
{
        return 16;
    }

    //当前的列表布局中有几种不同的分类,那么就在数组中定义n个不重复的数字
    int [] type =
{0,1,2};
    /*
    *  根据自定义的position判断条件,返回不同的viewType类型
    *  该方法优先于onCreateViewHolder方法先运行,并且
    *  该方法的返回值会被传递给onCreateViewHolder的参数二
    * */
    @Override
    public int getItemViewType(int position)
{
        if (position
>=0 && position <=4)
{
            return type[0];
        } else if (position
>= 5 && position <= 10)
{
            return type[1];
        } else {
            return type[2];
        }

    }
    //第一种布局对应的holder对象
    class MyDuoHolder1 extends RecyclerView.ViewHolder
{
        TextView duo1_tv;
        public MyDuoHolder1(View
itemView) {
            super(itemView);
            duo1_tv =
(TextView) itemView.findViewById(R.id.textView2);
        }
    }
    //第二种布局对应的holder对象
    class MyDuoHolder2 extends RecyclerView.ViewHolder
{

        TextView duo2_tv;
        ImageView duo2_iv;

        public MyDuoHolder2(View
itemView) {
            super(itemView);
            duo2_iv =
(ImageView)itemView.findViewById(R.id.imageView2);
            duo2_tv =
(TextView)itemView.findViewById(R.id.textView3);
        }
    }
    //第三种布局对应的holder对象
    class MyDuoHolder3 extends RecyclerView.ViewHolder
{

        ImageView duo3_iv1,duo3_iv2,duo3_iv3,duo3_iv4;
        public MyDuoHolder3(View
itemView) {
            super(itemView);
            duo3_iv1 =
(ImageView)itemView.findViewById(R.id.imageView3);
            duo3_iv2 =
(ImageView)itemView.findViewById(R.id.imageView4);
            duo3_iv3 =
(ImageView)itemView.findViewById(R.id.imageView5);
            duo3_iv4 =
(ImageView)itemView.findViewById(R.id.imageView6);

        }
    }

}
 
多布局的运行流程如下:
 
当getItemCount的返回值不为0时
 
针对于每一行要显示在屏幕上的item来说,运行流程为:
getItemViewType-----onCreateViewHolder(如果可以重用,则不运行此方法)-----OnBindViewHolder

RecyclerView实现GridView效果:
 
大体处理方式与实现ListView效果基本一致,只需修改LayoutManager的类型即可
导入外部library包,  包名为:com.android.support:recyclerview-v7:23.1.0
在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径
在代码中获取控件对象
设置LayoutManager(布局管理器),GridLayoutManager
设置适配器
RecyclerView实现瀑布流效果:
处理方式与上方基本一致,不同点为:
将设置的LayoutManger设置为StaggeredGridLayoutManager类型
在适配器中添加构造方法,在构造方法中处理每一个item控件要显示的高度,并通过集合存储起来
在onBindVIew方法中更改holder.item要显示的高度

当不想要通过设置margin设置间隔线时:
可通过以下方式进行设置:
控制Item间的间隔线
将路径:sdk\extras\android\support\samples\Support7Demos\src\com\example\android\supportv7\widget\decorator 中的DividerItemDecoration类拷贝到本工程中
通过addItemDecoration方法设置DividerItemDecoration对象即可添加间隔线
如需要自定义间隔线:在drawable文件夹中通过shape绘制任意形状
在AppTheme样式中添加:
<item name="android:listDivider">@drawable/divider_bg</item>

控制Item增删的动画
默认情况下自带动画
或者可以通过setItemAnimator方法设置自定义动画,
自定义的动画效果可参考github上的RecyclerViewItemAnimators工程的动画效果
RecyclerViewItemAnimators框架的使用:
 
先将该框架的library工程导入,
通过Project Structure使RecyclerView所在的工程添加library作为额外库工程,使本工程可以使用library工程中的动画效果类
如果想要实现设置自定义的添加或删除数据的动画:
 
//设置添加或删除数据时的动画效果
rv.setItemAnimator(new SlideInOutLeftItemAnimator(rv));
新增数据时:
list.add(3,"新增的数据");
adapter1.notifyItemInserted(3);
 
删除数据时:
list.remove(3);
adapter1.notifyItemRemoved(3);
/*
* 在参数指定范围内更新数据
* */
adapter1.notifyItemRangeChanged(3,list.size()-1);
 
 
如果想要实现让RecyclerView在初始显示时就显示动画:
 
//设置初始显示时的动画效果
adapter1 = new SlideInLeftAnimatorAdapter(new MyFirstAdapter(),rv);

//设置适配器
rv.setAdapter(adapter1);
 
当设置RecyclerView显示的时候,可以通过   rv.setHasFixSize(true)方法让RecyclerView更高效的进行加载显示

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: