RecyclerView简单使用(非常详细)

星期六,又是撸代码的一天
作为一个初级都算不上的小白,一步一个脚印的学吧,学一个记一个
今天记录的是RecyclerView

RecyclerView

  • 简述
  • 创建布局
    • 添加 RecyclerView和每个list布局(偏新手向,选择性跳过)
  • 创建适配器
      • 创建
      • onCreateViewHolder()
      • onBindViewHolder()
      • getItemCount()
  • 绑定适配器
      • 创建假数据
      • 绑定适配器
  • 适配器调整
      • 区别显示的实现
  • 点击事件

简述

官方解释为:提供一个固定的View让有限的窗口显示一个大数据集。(抄的)
我的理解是,和ListView差不多的东西
ListView是什么,不知道
总之,它可以呈现一系列数据,呈现方式可以根据给的LayoutManager确定

瀑布流(StaggeredGridLayoutManager)
RecyclerView简单使用(非常详细)_第1张图片

列表流 (LinearLayoutManager)

RecyclerView简单使用(非常详细)_第2张图片

表格流(GridLayoutManager)
RecyclerView简单使用(非常详细)_第3张图片

使用方式在下面的 绑定适配器

创建布局

添加 RecyclerView和每个list布局(偏新手向,选择性跳过)

第一步当然是在xml中添加,在Palette中找到RecyclerView,右键Add添加
RecyclerView简单使用(非常详细)_第4张图片
又或者在布局中写入Recy选择
RecyclerView简单使用(非常详细)_第5张图片
这时需要给RecyclerView添加id

android:id="@+id/recycler"

然后根据开发需求,创建一个xml文件,我这里命名为recy_list.xml
作为单个list的布局,我这里模仿聊天界面做了个xml
RecyclerView简单使用(非常详细)_第6张图片


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#cccccc"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:paddingRight="20dp"
    android:paddingLeft="20dp">


    <ImageView
        android:id="@+id/head"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="20dp"
        android:src="@android:mipmap/sym_def_app_icon" />


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="小白"
            android:textColor="@color/black"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/news"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="#666666"
            android:text="今天搬了多少砖"/>

    LinearLayout>

    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="end"
        android:textColor="#999999"
        android:textSize="14sp"
        android:text="2021年4月24日\n19:02:50"/>

LinearLayout>

最后在Activity绑定等等一系列操作

public class MainActivity extends AppCompatActivity {
     
 private RecyclerView recycler;//创建
  @Override
    protected void onCreate(Bundle savedInstanceState) {
     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();//初始化控件方法
    }

    private void initView() {
     
        recycler = findViewById(R.id.recycler);//绑定RecyclerView
    }

接下来进入重点,适配器

创建适配器

适配器Adapter,可以让开发者自定义recyclerview绑定的数据,通过上面创建的recy_list文件模板来创建一堆item

创建

  1. 创建一个Adapter类
  2. 继承RecyclerView的Adapte
  3. 泛型定义为Adapter的内部类MyHolder

具体是什么我也不知道,一堆复杂的词
大概就是这样

public class Adapter extends RecyclerView.Adapter<Adapter.MyHolder>  {
     
	@NonNull
    @Override
    public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
     
        return null;
    }

    @Override
    public void onBindViewHolder(@NonNull Adapter.MyHolder holder, int position) {
     

    }

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

然后Alt+回车生成一堆Adapter的接口,同时MyHolder变红,这个不管它,先来看这三方法干啥的

onCreateViewHolder()

  • 创建ViewHolder时的回调函数
  • 传入 ViewGroup parent 和 int viewType
  • 返回 MyHolder

MyHolder是list中每个item
这里使用LayoutInflater布局加载器来加载view,再将view传给内部类MyHolder用于实例化

    private View view;//在外面定义一个view
    
	@NonNull
    @Override
    public Adapter.MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
     
          view = LayoutInflater.from(context)//实例化LayoutInflater
                //传参 刚才创建的recy_list.xml
                .inflate(R.layout.recy_list, parent, false);
        Adapter.MyHolder myHolder= new Adapter.MyHolder(view);
        return myHolder;
    }

(要传contect,挖坑)
来说一下LayoutInflater,菜鸟教程的解释 LayoutInflater(布局服务)
RecyclerView简单使用(非常详细)_第7张图片

然后创建一个内部类MyHolder,继承ViewHolder ,在里面加上刚才的xml中的控件并绑定

  public class MyHolder extends RecyclerView.ViewHolder {
     
        TextView name, news, time;
        ImageView head;

        public MyHolder(View itemView) {
     
            super(itemView);
            name = itemView.findViewById(R.id.name);
            news = itemView.findViewById(R.id.news);
            time = itemView.findViewById(R.id.time);
            head = itemView.findViewById(R.id.head);
        }
    }

这时,第一个方法解决了!!

onBindViewHolder()

  • 绑定ViewHolder时的回调函数
  • 传入 自定义内部类的 holder 和 int position

激动人心的时候到了,终于绑定数据了

position
可以理解为list中item的下标,就像数组一样,每个item都有自己的标识
那数据怎么来,Adapter初始呗
新增构造方法,记得要传context,顺便加上成员变量

private Context context;
private ArrayList<String> nameList,newsList,timeList;

public Adapter(Context context, ArrayList nameList ,ArrayList newsList ,ArrayList timeList) {
     
        this.context = context;
        this.nameList = nameList;
        this.newsList = newsList;
        this.timeList = timeList;
    }

然后在onBindViewHolder方法中写绑定,根据position来给各个控件设置

 @Override
    public void onBindViewHolder(@NonNull ButViewHolder holder, int position) {
     
        //将数据和控件绑定
        holder.name.setText(nameList.get(position));
        holder.news.setText(newsList.get(position));
        holder.time.setText(timeList.get(position));
    }

就剩最后一个方法了

getItemCount()

没有传参,需要返回一个int
这个方法是控制创建item的条数,返回的就是条数
我这里直接给其中一个ArrayList的大小即可

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

三个方法搞定了,意味着这个简单的Adapter已经写完了
然后就是让RecyclerView绑定Adapter

绑定适配器

在Activity那边加一个方法,或者直接在onCreate里绑定
setRecyclerView();

创建假数据

 ArrayList name = new ArrayList();
        ArrayList news = new ArrayList();
        ArrayList time = new ArrayList();

        for (int i= 0;i<20;i++){
     
         name.add("小白    " + i);
            news.add("今天搬砖了?");
            time.add("2021年4月24日\n19:17:04");
        }

绑定适配器

	//适配器
 	RecyclerAdapter adapter = new RecyclerAdapter(this,name,news,time);
    //布局
    LinearLayoutManager manager = new LinearLayoutManager(this);
    //设置布局
    recycler.setLayoutManager(manager);
    //设置动画
    recycler.setItemAnimator(new DefaultItemAnimator());
    //设置适配器
    recycler.setAdapter(adapter);

就这样搞定了,这时运行项目就可以了看见本文开头那个列表流的效果了

适配器调整

都写到这了,再写一点吧

区别显示的实现

假如要给某一条item换上不同的背景
这时就需要在onBindViewHolder中修改
通过position,拿到ArrayList的某个数据进行判断
然后设置这个holder的某个控件的属性即可

点击事件

都九点半了,六千字,好累,写目录时加了这个,想删又不想删,还是写完再回家吧
Adapter点击事件的实现,需要声明View.OnClickListener接口
修改Adapter类,声明View.OnClickListener接口,加上一个onClick方法

public class Adapter 
	extends RecyclerView.Adapter<Adapter.MyHolder>
 	implements View.OnClickListener{
     

	@Override
    public void onClick(View v) {
     }
}

想要点击不同的item时做一些不同的事,就又又又要修改onBindViewHolder
给itemView设置点击事件

@Override
    public void onBindViewHolder(@NonNull ButViewHolder holder, int position) {
     
        //将数据和控件绑定
        holder.name.setText(nameList.get(position));
        holder.news.setText(newsList.get(position));
        holder.time.setText(timeList.get(position));
        
        holder.itemView.setOnClickListener(new View.OnClickListener() {
     
            @Override
            public void onClick(View v) {
     }
        });
    }

就这样???
如果我想在Activity中设置点击事件呢,比如跳转页面这种情况
添加点击事件接口,传值嘛
你想要什么就传什么,比如我想要点击的item的name,就传个name

 public interface OnItemClickListener {
     
        void onItemClick(String name);
    }

有接口,就要Activity那边实现,所以Adapter里新增一个方法
同时,接口里的方法需要传给成员变量

private OnItemClickListener mListener;

public void setOnItemClickListener(OnItemClickListener li) {
     
        mListener = li;
    }

最后在绑定中的点击事件中添加

holder.itemView.setOnClickListener(new View.OnClickListener() {
     
            @Override
            public void onClick(View v) {
     
            	mListener.onItemClick(nameList.get(position));
            }
        });

这么说好像有些别扭
总结就是

  1. Adapter创建点击事件接口
  2. Activity实现接口
  3. 实现后的接口存入Adapter的成员变量
  4. 当点击item时,触发onBindViewHolder中设置的绑定事件
  5. 绑定事件执行的是 Activity中传给成员变量的方法

这时,点击事件已经完成,就这样吧,回家咯!
下次有时间写个加头或尾的文章类似于B站的独占一行方法

不要在意内容!!!

对本文有任何意见或疑问,或者认为其中说法有误,欢迎在评论区留言!!!
最后,转载请注明出处!!

你可能感兴趣的:(android,移动开发,安卓)