RecycleView的基础使用

RecycleView
5.0之后的新控件
作用用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView
可以实现ListViewGridView的效果
可以瀑布流效果
可以方便列表多布局效果
再删除或者增加条目时,支持动画效果
自带View复用效果
使用方式:
控制显示方式
  • 给当前工程添加com.android.support.recyclerview-v7类库
导入外部library包,  包名为:com.android.support:recyclerview-v7:23.1.0在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径
  • 在代码中获取控件对象
  • 设置布局管理器
    • LinearLayoutManager    线性布局管理器,支持横向,纵向
    • GridLayoutManager    网格布局管理器
    • StaggeredGridLayoutManager    瀑布流式布局管理器 

此处设置布局管理器的目的在于:由于RecyclerView控件可以实现ListViewGridVIew等多种效果,因此需要通过布局管理器来通知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工程的动画效果

适配器创建的步骤:

  1. 创建一个RecyclerView.Adapter的子类,
  2. 在该子类内部创建一个RecyclerView.ViewHolder的子类,在该类的构造方法中,处理每行的item中的控件的初始化
  3. 将适配器子类声明时的泛型修改为第2步中ViewHolder子类类型
  4. 重写适配器子类中的方法

 

/*
创建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中的每个控件上要显示什么样的数据

设置RecyclerViewItem的点击事件

RecyclerView中并不存在显示的item点击的监听事件,因此想要获取item的点击事件及获取被点击的itemposition时, 添加点击事件的方式为:

/*
* 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 >=&& position <=4) {
            return type[0];
        } else if (position >= && 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的类型即可

  1. 导入外部library包,  包名为:com.android.support:recyclerview-v7:23.1.0
  2. 在布局文件中添加要显示的RecyclerView控件,注意:标签名要写RecyclerView的完整路径
  3. 在代码中获取控件对象
  4. 设置LayoutManager(布局管理器),GridLayoutManager
  5. 设置适配器

RecyclerView实现瀑布流效果:

处理方式与上方基本一致,不同点为:

  1. 将设置的LayoutManger设置为StaggeredGridLayoutManager类型
  2. 在适配器中添加构造方法,在构造方法中处理每一个item控件要显示的高度,并通过集合存储起来
  3. 在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框架的使用:

 

  1. 先将该框架的library工程导入,
  2. 通过Project Structure使RecyclerView所在的工程添加library作为额外库工程,使本工程可以使用library工程中的动画效果类
  3. 如果想要实现设置自定义的添加或删除数据的动画:

 

//设置添加或删除数据时的动画效果
rv.setItemAnimator(new SlideInOutLeftItemAnimator(rv));

新增数据时:

list.add(3,"新增的数据");
adapter1.notifyItemInserted(3);

 

删除数据时:

list.remove(3);
adapter1.notifyItemRemoved(3);
/*
在参数指定范围内更新数据
* */
adapter1.notifyItemRangeChanged(3,list.size()-1);

 

 

  1. 如果想要实现让RecyclerView在初始显示时就显示动画:

 

//设置初始显示时的动画效果
adapter1 new SlideInLeftAnimatorAdapter(new MyFirstAdapter(),rv);

//设置适配器
rv.setAdapter(adapter1);

 

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



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值