曂沅仴駦 发表于 2024-8-29 23:18:16

Android常见结构控件(四)

https://i-blog.csdnimg.cn/direct/1e33417ce4e94c03a200926baf506ccf.gif

目次

前言
RecyclerView控件
数据适配器
结构管理器
使用RecyclerView
创建XML结构文件
创建ReActivity类
创建数据适配器
onCreateViewHolder
onBindViewHolder
 完整代码
补充知识
ItemDecoration

前言

在前一篇中,我们讲解了ListView控件,那么本篇我们就来讲解RecyclerView控件
RecyclerView控件

与ListView类似,RecyclerView控件同样也是以列表的形式将数据进行展示,都是为了维护少量的View来进行显示大量的数据。是在android5.0之后新添的控件,用来替代传统的ListView和GridView控件的。
与传统的ListView不同,RecyclerView能通过LayoutManager类来实现横向或者竖向的列表效果、瀑布流效果和GridView效果,而ListView只能实现竖直的列表效果。

格式如下:
    <androidx.recyclerview.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="match_parent"/> 我们 可以通过在Patale中找到RecylcerView,将其拉到XML文件中
https://i-blog.csdnimg.cn/direct/1e606cbad5b644f09e2e145dc5143794.png
当然,我们也可以手动添加:
https://i-blog.csdnimg.cn/direct/f5a0ec90294f44d4ba937ac1fbabfabd.png

数据适配器

RecyclerView控件使用的是RecyclerView.Adapter,该数据适配器将BaseAdapter中的getView()方法拆解为onCreateViewHolder()方法和onBindViewHolder()方法,强制使用ViewHolder类,使代码更加规范化。
结构管理器

LayoutManager结构管理器用来设置每一项view在RecyclerView中的位置结构,以及控件item view的显示或隐藏。当View重用或者回收的时候,LayoutManager都会向Adapter来请求新的数据进行替换原来的数据的内容。这种回收复用机制可以提供性能,克制创建许多的view或者是频仍的调用findViewById()方法。
RcyclerView提供了三种内置的LayoutManager:


[*]LinearLayoutManager:线性结构,横向或者纵向滑动列表
[*]GridLayoutManager:网格结构
[*]StaggerdGridLayoutManager:流式结构,如瀑布流效果。
当然,我们也可以通过继续RecyclerView.LayoutManager来实现一个自界说的LayoutManager。
Animations(动画)效果:


[*]RecyclerView对于Item的添加和删除是默认开启动画的,我们也可以通过RecyclerView.ItemAnimator类来定制动画,再通过RecyclerView.setItemAnimator()方法来使用
以下是RecyclerView的一些相关类:
类名阐明RecyclerView.Adapter可以托管数据集合,为每一项Item创建视图并且绑定数据RecyclerView.ViewHolder承载Item视图的子结构RecyclerView.LayoutManager负责Item视图的结构的显示管理RecyclerView.ItemDecoration给每一项Item视图添加子View,例如进行画分割线等RecyclerView.ItemAnimator负责处理数据添加或者删除时候的动画效果 使用RecyclerView

创建XML结构文件

这里我选择创建一个名为recycle_list.xml的结构文件。
这里我们选择模仿聊天的界面,那么起首我们需要实现一个聊天的界面,就在上面创建的结构中实现。效果图如下:
https://i-blog.csdnimg.cn/direct/d1aa0b6260f74ba3a92888241a2cfb70.png
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp">

    <ImageView
      android:id="@+id/tv"
      android:src="@mipmap/ic_launcher"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"/>
    <LinearLayout
      android:layout_width="200dp"
      android:layout_height="match_parent"
      android:layout_marginLeft="10dp"
      android:orientation="vertical">
      <TextView
            android:id="@+id/tv_name"
            android:text="李四"
            android:textStyle="bold"
            android:textSize="20sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
      <TextView
            android:id="@+id/news"
            android:text="李四,你今天在干嘛呢?"
            android:textSize="15sp"
            android:layout_marginTop="15sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <TextView
      android:id="@+id/tv_time"
      android:gravity="end"
      android:text="24/8/25\n12:00"
      android:textColor="#999999"
      android:textSize="15sp"
      android:layout_width="wrap_content"
      android:layout_weight="1"
      android:layout_height="match_parent"/>
</LinearLayout> 同时,我们可以创建一个recycle_main.xml结构用来显示聊天界面,在其中放入RecyclerView控件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
   
    <androidx.recyclerview.widget.RecyclerView
      android:id="@+id/recyclerView"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>
</LinearLayout> 创建ReActivity类

我们既然已经把结构文件做好,那么现在就是有关java的代码了,我们需要创建一个ReActivity类,在里面来进行绑定结构文件等操作。

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;

public class ReActivity extends AppCompatActivity {

    private RecyclerView recyclerView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.recycle_main);
      Init();
    }

    private void Init() {
      recyclerView = findViewById(R.id.recyclerView);//初始化recyclerView
    }
}
创建数据适配器

在上面,我们已经把聊天的界面以及RecyclerView控件创建出来了,那么接下来我们就来自界说一个适配器继续RecyclerView.Adapter来创建item view以及绑定数据.
onCreateViewHolder

步调:


[*]创建适配器类继续RecyclerView.Adapter,传入泛型
[*]创建内部类即RecyclerView.ViewHolder的子类,并初始化item控件。
[*]重写RecyclerView.Adapter类的相关方法。
这里我们使用View.inflate来加载v,并将v传给内部类MyAdapter(本身实现)继续实例化。
      private View v;
      private MyAdapter myAdapter;

      @NonNull
      @Override
      public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            v = View.inflate(ReActivity.this,R.layout.recycle_list,null);
            myAdapter = new MyAdapter(v);
            return myAdapter;
      }
这里创建一个内部类MyAdapter继续ViewHolder,绑定传进来的v的控件。
class MyAdapter extends RecyclerView.ViewHolder {
            TextView name, news, time;
            ImageView image;

            public MyAdapter(@NonNull View itemView) {
                super(itemView);
                name = itemView.findViewById(R.id.tv_name);
                news = itemView.findViewById(R.id.news);
                time = itemView.findViewById(R.id.tv_time);
            }
      } onBindViewHolder



[*]将获取到的数据设置到对应的控件上。
[*]传入类的holder和position
position相当于下标,既然需要获取类的数据,那么我们需要一个构造方法来初始化类的数据
      private final Context context;
      private final ArrayList nameList,timeList,newsList;
      public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
            this.context = context;
            this.nameList = nameList;
            this.newsList = newsList;
            this.timeList = timeList;
      }
到这,我们已经把自界说的适配器Adapter实现完成,完整代码:
/**
   * RecyclerView的适配器类
   */
    class Adapter extends RecyclerView.Adapter<Adapter.MyAdapter> {
      private Context context;
      private ArrayList nameList, newsList, timeList;

      /**
         * Adapter构造方法
         * @param context 上下文环境,此处为ReActivity实例
         * @param nameList 名称数据列表
         * @param newsList 消息数据列表
         * @param timeList 时间数据列表
         */
      public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
            this.context = context;
            this.nameList = nameList;
            this.newsList = newsList;
            this.timeList = timeList;
      }

      /**
         * 创建ViewHolder
         * @param parent 父容器,用于容纳RecyclerView项视图
         * @param viewType 视图类型,此处未使用
         * @return 创建的ViewHolder实例
         */
      @NonNull
      @Override
      public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v = View.inflate(ReActivity.this,R.layout.recycle_list,null); // 加载RecyclerView项布局文件
            MyAdapter myAdapter = new MyAdapter(v); // 创建ViewHolder
            return myAdapter;
      }

      /**
         * 绑定ViewHolder数据
         * @param holder ViewHolder实例,用于展示数据
         * @param position 数据源中的位置
         */
      @Override
      public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
            holder.name.setText(nameList.get(position).toString()); // 设置名称文本
            holder.news.setText(newsList.get(position).toString()); // 设置消息文本
            holder.time.setText(timeList.get(position).toString()); // 设置时间文本
      }

      /**
         * 返回数据源中项的数量
         * @return 数据源大小
         */
      @Override
      public int getItemCount() {
            return nameList.size();
      }

      /**
         * RecyclerView ViewHolder子类
         */
      class MyAdapter extends RecyclerView.ViewHolder {
            TextView name, news, time;
            ImageView image;

            /**
             * MyAdapter构造方法,用于初始化ViewHolder中的视图组件
             * @param itemView RecyclerView项的根视图
             */
            public MyAdapter(@NonNull View itemView) {
                super(itemView);
                name = itemView.findViewById(R.id.tv_name); // 初始化名称文本视图
                news = itemView.findViewById(R.id.news); // 初始化消息文本视图
                time = itemView.findViewById(R.id.tv_time); // 初始化时间文本视图
            }
      }
    } 接下来,我们就在我们界说的Init()方法中来实例化这些类以及调用相关的方法。


[*]起首实例化存储数据的三个ArrayList,分别存储用户名,信息,时间。并模仿天生一些数据。
[*]创建Adapter对象并将上面三个ArratList传入
[*]创建线性结构管理器,并给前面的rercyclerView设置结构为线性结构。
[*]给rercyclerView设置每一项的动画,并且设置分割线和适配器
/**
   * 初始化方法,用于初始化RecyclerView组件及适配器
   */
    private void Init() {
      recyclerView = findViewById(R.id.recyclerView); // 初始化RecyclerView组件
      // 初始化存储数据的ArrayList
      ArrayList names = new ArrayList();
      ArrayList newsList = new ArrayList();
      ArrayList timeList = new ArrayList();
      // 循环生成模拟数据
      for(int i=0;i<50;i++){
            names.add("00"+i);
            newsList.add("你今天在干嘛呢?");
            timeList.add("2020-01-01 \n15:"+i);
      }
      // 创建Adapter实例并传入数据源
      Adapter adapter = new Adapter(this ,names,newsList,timeList);
      // 创建LinearLayoutManager实例,用于管理RecyclerView的布局
      LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
      recyclerView.setLayoutManager(linearLayoutManager); // 设置RecyclerView的布局管理器
      recyclerView.setItemAnimator(new DefaultItemAnimator()); // 设置RecyclerView的项动画
      recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL)); // 添加分割线装饰
      recyclerView.setAdapter(adapter); // 设置RecyclerView的适配器
    }  完整代码

ReActivity.java
import android.content.Context;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.DefaultItemAnimator;import androidx.recyclerview.widget.DividerItemDecoration;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;// ReActivity类继续自AppCompatActivity,用于展示RecyclerView实现的列表界面public class ReActivity extends AppCompatActivity {    // 声明RecyclerView对象    private RecyclerView recyclerView;    /**   * onCreate方法,在活动创建时调用   * @param savedInstanceState 大概存在的保存实例状态Bundle,此处为可空   */    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      setContentView(R.layout.recycle_main); // 设置活动的结构文件      Init(); // 初始化组件和数据    }    /**
   * 初始化方法,用于初始化RecyclerView组件及适配器
   */
    private void Init() {
      recyclerView = findViewById(R.id.recyclerView); // 初始化RecyclerView组件
      // 初始化存储数据的ArrayList
      ArrayList names = new ArrayList();
      ArrayList newsList = new ArrayList();
      ArrayList timeList = new ArrayList();
      // 循环生成模拟数据
      for(int i=0;i<50;i++){
            names.add("00"+i);
            newsList.add("你今天在干嘛呢?");
            timeList.add("2020-01-01 \n15:"+i);
      }
      // 创建Adapter实例并传入数据源
      Adapter adapter = new Adapter(this ,names,newsList,timeList);
      // 创建LinearLayoutManager实例,用于管理RecyclerView的布局
      LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
      recyclerView.setLayoutManager(linearLayoutManager); // 设置RecyclerView的布局管理器
      recyclerView.setItemAnimator(new DefaultItemAnimator()); // 设置RecyclerView的项动画
      recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL)); // 添加分割线装饰
      recyclerView.setAdapter(adapter); // 设置RecyclerView的适配器
    }    /**
   * RecyclerView的适配器类
   */
    class Adapter extends RecyclerView.Adapter<Adapter.MyAdapter> {
      private Context context;
      private ArrayList nameList, newsList, timeList;

      /**
         * Adapter构造方法
         * @param context 上下文环境,此处为ReActivity实例
         * @param nameList 名称数据列表
         * @param newsList 消息数据列表
         * @param timeList 时间数据列表
         */
      public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
            this.context = context;
            this.nameList = nameList;
            this.newsList = newsList;
            this.timeList = timeList;
      }

      /**
         * 创建ViewHolder
         * @param parent 父容器,用于容纳RecyclerView项视图
         * @param viewType 视图类型,此处未使用
         * @return 创建的ViewHolder实例
         */
      @NonNull
      @Override
      public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v = View.inflate(ReActivity.this,R.layout.recycle_list,null); // 加载RecyclerView项布局文件
            MyAdapter myAdapter = new MyAdapter(v); // 创建ViewHolder
            return myAdapter;
      }

      /**
         * 绑定ViewHolder数据
         * @param holder ViewHolder实例,用于展示数据
         * @param position 数据源中的位置
         */
      @Override
      public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
            holder.name.setText(nameList.get(position).toString()); // 设置名称文本
            holder.news.setText(newsList.get(position).toString()); // 设置消息文本
            holder.time.setText(timeList.get(position).toString()); // 设置时间文本
      }

      /**
         * 返回数据源中项的数量
         * @return 数据源大小
         */
      @Override
      public int getItemCount() {
            return nameList.size();
      }

      /**
         * RecyclerView ViewHolder子类
         */
      class MyAdapter extends RecyclerView.ViewHolder {
            TextView name, news, time;
            ImageView image;

            /**
             * MyAdapter构造方法,用于初始化ViewHolder中的视图组件
             * @param itemView RecyclerView项的根视图
             */
            public MyAdapter(@NonNull View itemView) {
                super(itemView);
                name = itemView.findViewById(R.id.tv_name); // 初始化名称文本视图
                news = itemView.findViewById(R.id.news); // 初始化消息文本视图
                time = itemView.findViewById(R.id.tv_time); // 初始化时间文本视图
            }
      }
    }} 结合前面的两个XML结构,运行即可得到:
https://i-blog.csdnimg.cn/direct/3081e4b3b2b84b8bb30cc02a8ed7a4dd.gif
补充知识

ItemDecoration

在使用RecyclerView的时候,如果我们想要设置分割线,那么我们可以通过ItemDecoration。例如:
      DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);分割线
      recyclerView.addItemDecoration(decoration); // 添加分割线装饰  https://i-blog.csdnimg.cn/direct/d4a6032583eb427d9502fe378b7e28dc.png
Item动画
在RecyclerView中提供了默认的IntemAnimator实现类: DefaulttemAnimator。我们可以借助该类帮我们实现一些动画。
      DefaultItemAnimator animator = new DefaultItemAnimator();
      animator.setAddDuration(1000);
      animator.setRemoveDuration(1000);
      recyclerView.setItemAnimator(animator); // 设置RecyclerView的项动画 在前面的基础上,在recycle_main.xml聊天界面的上部添加两个按钮(添加和删除)
<LinearLayout
      android:layout_marginLeft="80dp"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">
      <Button
            android:id="@+id/add"
            android:text="添加Item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
      <Button
            android:id="@+id/del"
            android:text="删除Item"
            android:layout_marginLeft="60dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout> 同时在ReActivity类中添加对应点击变乱(由于代码有改动,以是这里直接放全部代码):
package com.example.newapptext1;import android.content.Context;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.DefaultItemAnimator;import androidx.recyclerview.widget.DividerItemDecoration;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;// ReActivity类继续自AppCompatActivity,用于展示RecyclerView实现的列表界面public class ReActivity extends AppCompatActivity implements View.OnClickListener {    // 声明RecyclerView对象    private RecyclerView recyclerView;    private Adapter adapter;    private ArrayList names;    private ArrayList newsList;    private ArrayList timeList;    /**   * onCreate方法,在活动创建时调用   * @param savedInstanceState 大概存在的保存实例状态Bundle,此处为可空   */    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      setContentView(R.layout.recycle_main); // 设置活动的结构文件      Init(); // 初始化组件和数据    }    /**   * 初始化方法,用于初始化RecyclerView组件及适配器   */    private void Init() {      recyclerView = findViewById(R.id.recyclerView); // 初始化RecyclerView组件      // 初始化存储数据的ArrayList      names = new ArrayList();      newsList = new ArrayList();      timeList = new ArrayList();      // 循环天生模仿数据      for(int i=0;i<5;i++){            names.add("00"+i);            newsList.add("你今天在干嘛呢?");            timeList.add("2020-01-01 \n15:"+i);      }      // 创建Adapter实例并传入数据源      adapter = new Adapter(this , names, newsList, timeList);      // 创建LinearLayoutManager实例,用于管理RecyclerView的结构      LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);      linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); // 设置垂直方向      recyclerView.setLayoutManager(linearLayoutManager); // 设置RecyclerView的结构管理器      DefaultItemAnimator animator = new DefaultItemAnimator();
      animator.setAddDuration(1000);
      animator.setRemoveDuration(1000);
      recyclerView.setItemAnimator(animator); // 设置RecyclerView的项动画      DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);分割线
      recyclerView.addItemDecoration(decoration); // 添加分割线装饰      recyclerView.setAdapter(adapter); // 设置RecyclerView的适配器      //添加点击变乱      findViewById(R.id.add).setOnClickListener(this);      findViewById(R.id.del).setOnClickListener(this);    }    @Override    public void onClick(View view) {      // 判断点击的视图是否为添加按钮      if(view.getId()==R.id.add){            // 向列表中添加新的名字和消息,用于模仿新消息的到来            names.add(1,"新添");            newsList.add(1,"你在干嘛呢?");            timeList.add(1,"2020-01-01 \n15:00");            // 通知适配器插入新项,以便更新UI            adapter.notifyItemInserted(1);      } else if(view.getId()==R.id.del){            // 判断点击的视图是否为删除按钮            // 从名字、消息和时间列表中移除指定位置的元素,以模仿数据删除操作            names.remove(1);            newsList.remove(1);            timeList.remove(1);            // 通知适配器移除项,以便更新UI            adapter.notifyItemRemoved(1);      }    }    /**
   * RecyclerView的适配器类
   */
    class Adapter extends RecyclerView.Adapter<Adapter.MyAdapter> {
      private Context context;
      private ArrayList nameList, newsList, timeList;

      /**
         * Adapter构造方法
         * @param context 上下文环境,此处为ReActivity实例
         * @param nameList 名称数据列表
         * @param newsList 消息数据列表
         * @param timeList 时间数据列表
         */
      public Adapter(Context context, ArrayList nameList, ArrayList newsList, ArrayList timeList){
            this.context = context;
            this.nameList = nameList;
            this.newsList = newsList;
            this.timeList = timeList;
      }

      /**
         * 创建ViewHolder
         * @param parent 父容器,用于容纳RecyclerView项视图
         * @param viewType 视图类型,此处未使用
         * @return 创建的ViewHolder实例
         */
      @NonNull
      @Override
      public MyAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v = View.inflate(ReActivity.this,R.layout.recycle_list,null); // 加载RecyclerView项布局文件
            MyAdapter myAdapter = new MyAdapter(v); // 创建ViewHolder
            return myAdapter;
      }

      /**
         * 绑定ViewHolder数据
         * @param holder ViewHolder实例,用于展示数据
         * @param position 数据源中的位置
         */
      @Override
      public void onBindViewHolder(@NonNull MyAdapter holder, int position) {
            holder.name.setText(nameList.get(position).toString()); // 设置名称文本
            holder.news.setText(newsList.get(position).toString()); // 设置消息文本
            holder.time.setText(timeList.get(position).toString()); // 设置时间文本
      }

      /**
         * 返回数据源中项的数量
         * @return 数据源大小
         */
      @Override
      public int getItemCount() {
            return nameList.size();
      }

      /**
         * RecyclerView ViewHolder子类
         */
      class MyAdapter extends RecyclerView.ViewHolder {
            TextView name, news, time;
            ImageView image;

            /**
             * MyAdapter构造方法,用于初始化ViewHolder中的视图组件
             * @param itemView RecyclerView项的根视图
             */
            public MyAdapter(@NonNull View itemView) {
                super(itemView);
                name = itemView.findViewById(R.id.tv_name); // 初始化名称文本视图
                news = itemView.findViewById(R.id.news); // 初始化消息文本视图
                time = itemView.findViewById(R.id.tv_time); // 初始化时间文本视图
            }
      }
    }} 运行之后可以得到:
https://i-blog.csdnimg.cn/direct/607a3a42e7b240f38fcacac73401b5ce.gif
当然,尚有个革新功能,后面再跟各人讲。
以上就是本篇所有内容,如有不敷,欢迎指正~ https://i-blog.csdnimg.cn/direct/1a5fa8546f094609a75148e3dc6212fe.gif

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Android常见结构控件(四)