美文网首页
Android 使用 RecyclerView 创建动态列表

Android 使用 RecyclerView 创建动态列表

作者: 小城哇哇 | 来源:发表于2022-11-05 22:07 被阅读0次
  • Recyclerview 认识

    • Recyclerview 库
    • Recyclerview 指南
    • RecyclerView 可以显示大型数据集,通过回收有限数量的视图可以有效地滚动这些数据集,同时最大限度减少内存用量。 在实例化 ViewHolder 视图时可以定义单击侦听器。
    • RecyclerView 库会根据需要动态创建元素。顾名思义,RecyclerView 会回收这些单个的元素。当列表项滚动出屏幕时,RecyclerView 不会销毁其视图。相反,RecyclerView 会对屏幕上滚动的新列表项重用该视图。这种重用可以显著提高性能,改善应用响应能力并降低功耗。* 使用:在应用或模块的 build.gradle 文件中添加所需工件的依赖项:
    dependencies {
      implementation "androidx.recyclerview:recyclerview:1.2.1"
    }
    
    
    • 第二步:定义页面布局 (activity_out_in.xml)
      <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".ui.warehouse.OutInActivity">
          <!-- 省略其他布局内容 ,保留 RecyclerView -->
          <!-- 标题 -->
          <!-- 条件查询部分 -->
          <!-- 内容   -->
          <androidx.recyclerview.widget.RecyclerView
              android:id="@+id/OutIn_page_recyclerview"
              android:layout_width="0dp"
              android:layout_height="0dp"
              app:layout_constraintBottom_toBottomOf="parent"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toBottomOf="@id/card_OutIn_page_query" />
      </androidx.constraintlayout.widget.ConstraintLayout>
    复制代码
    
    • 第三步:定义RecyclerView每一项(Item)页面(recyclerview_ware_item.xml)
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <androidx.cardview.widget.CardView
            android:id="@+id/ware_card"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/f_mp_10_lr"
            android:layout_marginTop="5dp"
            android:layout_marginRight="@dimen/f_mp_10_lr"
            android:layout_marginBottom="5dp"
            app:cardCornerRadius="5dp"
            app:cardElevation="5dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/f_mp_20_lr">
              <!-- 通过预设尺寸,指定文字大小。注意: layout_height、layout_width这两个属性,不同的用法有意想不到的惊喜 -->
              <!-- app:autoSizeText 属性设置为 none 或 uniform。none 是默认值,而 uniform 可让 TextView 在水平和垂直轴上均匀缩放。 -->
              <!-- app:autoSizePresetSizes="@array/auto_size_text_sizes" 属性设置为预设尺寸数组。如要将该数组作为资源来访问,请在 res/values/arrays.xml 文件中定义该数组。 -->
                <TextView
                    android:id="@+id/tvIt_material_name"
                    android:layout_width="wrap_content"
                    android:layout_height="25dp"
                    android:gravity="center|left"
                    android:maxWidth="220dp"
                    android:minWidth="160dp"
                    android:text="物品测试的测试测试"
                    app:autoSizePresetSizes="@array/auto_size_text_sizes"
                    app:autoSizeTextType="uniform"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
                <TextView
                    android:id="@+id/tvIt_number_name"
                    android:layout_width="60dp"
                    android:layout_height="25dp"
                    android:gravity="center|left"
                    android:text="出库数量:"
                    app:autoSizePresetSizes="@array/auto_size_text_sizes"
                    app:autoSizeTextType="uniform"
                    app:layout_constraintEnd_toStartOf="@+id/tvIT_unit_num"
                    app:layout_constraintTop_toTopOf="parent" />
                <TextView
                    android:id="@+id/tvIT_unit_num"
                    android:layout_width="55dp"
                    android:layout_height="25dp"
                    android:gravity="center|right"
                    android:text="1008/只"
                    app:autoSizePresetSizes="@array/auto_size_text_sizes"
                    app:autoSizeTextType="uniform"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
                <TextView
                    android:id="@+id/tvIT_date_name"
                    android:layout_width="60dp"
                    android:layout_height="25dp"
                    android:layout_marginTop="5dp"
                    android:gravity="center|left"
                    android:text="出库日期:"
                    app:autoSizePresetSizes="@array/auto_size_text_sizes"
                    app:autoSizeTextType="uniform"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/tvIt_material_name" />
                <TextView
                    android:id="@+id/tvIT_date"
                    android:layout_width="wrap_content"
                    android:layout_height="25dp"
                    android:layout_marginTop="5dp"
                    android:layout_marginBottom="5dp"
                    android:gravity="center"
                    android:text="2022-10-11"
                    app:layout_constraintStart_toEndOf="@+id/tvIT_date_name"
                    app:layout_constraintTop_toBottomOf="@+id/tvIt_material_name" />
                <TextView
                    android:id="@+id/tvIT_ware_status_name"
                    android:layout_width="60dp"
                    android:layout_height="25dp"
                    android:layout_marginTop="5dp"
                    android:gravity="center|left"
                    android:text="出库状态:"
                    app:autoSizePresetSizes="@array/auto_size_text_sizes"
                    app:autoSizeTextType="uniform"
                    app:layout_constraintEnd_toStartOf="@+id/tvIT_ware_status"
                    app:layout_constraintTop_toBottomOf="@+id/tvIt_number_name" />
                <TextView
                    android:id="@+id/tvIT_ware_status"
                    android:layout_width="55dp"
                    android:layout_height="25dp"
                    android:layout_marginTop="5dp"
                    android:gravity="center"
                    android:text="销售"
                    app:autoSizePresetSizes="@array/auto_Item_size"
                    app:autoSizeTextType="uniform"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/tvIT_unit_num" />
            </androidx.constraintlayout.widget.ConstraintLayout>
            <TextView
                android:id="@+id/tvIT_ware_out_in"
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:layout_marginTop="6dp"
                android:background="@color/blue"
                android:gravity="center"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:rotation="45"
                android:text="出库"
                android:textColor="@color/white"
                android:textSize="10sp"
                android:translationX="12dp"
                android:translationZ="@dimen/f_mp_10_lr"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        </androidx.cardview.widget.CardView>
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    • 第四步 :创建RecyclerView适配器 ,实现 Adapter 和 ViewHolder

    • ViewHolder 是包含列表中各列表项的布局的 View 的封装容器。Adapter 会根据需要创建 ViewHolder 对象,还会为这些视图设置数据。将视图与其数据相关联的过程称为“绑定”。

    • 定义 Adapter,需要重写以下三个方法

      • onCreateViewHolder():每当 RecyclerView 需要创建新的 ViewHolder 时,它都会调用此方法。此方法会创建并初始化 ViewHolder 及其关联的 View,但不会填充视图的内容,因为 ViewHolder 此时尚未绑定到具体数据。
      • onBindViewHolder():RecyclerView 调用此方法将 ViewHolder 与数据相关联。此方法会提取适当的数据,并使用该数据填充 ViewHolder 的布局。
      • getItemCount():RecyclerView 调用此方法来获取数据集的大小。
        //数据源 实体类对象
        public class TestData {
          private int testId;
          private String testName;
          private String testNum;
          private String testDate;
          private String testStatus;
          private String testOutIn;
          //构造方法 。getter 和 setter 方法省略不写(不展示出来)
        }
      
      
        import android.content.Context;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.ViewGroup;
        import android.widget.TextView;
        import androidx.annotation.NonNull;
        import androidx.recyclerview.widget.RecyclerView;
        import java.util.List;
        //部分涉及 项目包名 导入(没写出来)
        //创建 RecyclerView 适配器 。继承于RecyclerView.Adapter<VH>,其中VH是我们创建的一个继承于RecyclerView.ViewHolder的静态内部类
        public class WareRecyclerViewAdapter extends RecyclerView.Adapter<WareRecyclerViewAdapter.myView> {
          private List<TestData> dataList; // 数据源
          private Context context;//上下文
          private myItemOnClick myItemOnClick ;
          //第一步:创建 myItemOnClick 接口
          public interface myItemOnClick {
            void onItemClick(int position);
          }
          //声明给外界方法
          public void setItemOnClick(myItemOnClick myItemOnClick) {
            this.myItemOnClick = myItemOnClick;
          }
          public WareRecyclerViewAdapter(Context context, List<TestData> dataList) {
            this.dataList = dataList;
            this.context = context;
          }
      
          //初始化item布局
          @NonNull
          @Override
          public myView onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            //        View view = View.inflate(context, R.layout.recyclerview_ware_item, null); //写法一
            //写法二  解决item宽度不能铺满
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_ware_item, parent, false);
            return new myView(view);
          }
      
          //绑定元素的数据
          @Override
          public void onBindViewHolder(@NonNull myView holder, int position) {
            holder.itMaterial.setText(dataList.get(position).getTestName());
            holder.itUnitNum.setText(dataList.get(position).getTestNum());
            holder.itDate.setText(dataList.get(position).getTestDate());
            holder.itStatus.setText(dataList.get(position).getTestStatus());
            holder.itWareOutIn.setText(dataList.get(position).getTestOutIn());
      
            String OutIn=dataList.get(position).getTestOutIn();
              if (OutIn.equals("出库")) {
                holder.itNumber.setText(context.getString(R.string.OutNumber) + ":");
                holder.itDateName.setText(context.getString(R.string.OutDate) + ":");
                holder.itStatusName.setText(context.getString(R.string.OutStatus) + ":");
                holder.itWareOutIn.setBackgroundColor(context.getResources().getColor(R.color.aurantius));//右上角标识
                holder.itDate.setTextColor(context.getResources().getColor(R.color.aurantius));//出库日期
                holder.itStatus.setTextColor(context.getResources().getColor(R.color.aurantius));//出库用途
              }
              if (OutIn.equals("入库")) {
                holder.itNumber.setText(context.getString(R.string.InNumber) + ":");
                holder.itDateName.setText(context.getString(R.string.InDate) + ":");
                holder.itStatusName.setText(context.getString(R.string.InStatus) + ":");
                holder.itWareOutIn.setBackgroundColor(context.getResources().getColor(R.color.green));//右上角标识
                holder.itDate.setTextColor(context.getResources().getColor(R.color.green));//入库日期
                holder.itStatus.setTextColor(context.getResources().getColor(R.color.green));//入库状态
              }
      
            //给每一项item 添加点击事件  //实际上的触发的点击事件
            if (myItemOnClick!=null) {
              holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                  myItemOnClick.onItemClick(holder.getLayoutPosition());
                }
              });
            }
          }
      
          /*获取数据的总数据量*/
          @Override
          public int getItemCount() {
            return dataList == null ? 0 : dataList.size();
          }
      
          //获取元素
          public class myView extends RecyclerView.ViewHolder {
            private TextView itMaterial, itNumber, itUnitNum, itDateName, itDate, itStatusName, itStatus, itWareOutIn,
                    itRepair1,itRepair2,itRepair3,itRepair4,itRepair5,itRepair6,itRepair7,itRepair8;
            private ConstraintLayout repair_constraint;
            public myView(@NonNull View itemView) {
              super(itemView);
              itMaterial = itemView.findViewById(R.id.tvIt_material_name);//物品名称
              itNumber = itemView.findViewById(R.id.tvIt_number_name); //出入库数量
              itUnitNum = itemView.findViewById(R.id.tvIT_unit_num);//具体数据+单位
              itDateName = itemView.findViewById(R.id.tvIT_date_name);//出入库日期
              itDate = itemView.findViewById(R.id.tvIT_date);//具体日期
              itStatusName = itemView.findViewById(R.id.tvIT_ware_status_name);//出入库状态
              itStatus = itemView.findViewById(R.id.tvIT_ware_status);//出入库状态值
              itWareOutIn = itemView.findViewById(R.id.tvIT_ware_out_in);//出入库标识
            }
          }
        }
      
      
      • 第五步:使用RecyclerView的适配器:recycleView.setAdapter(adapter)
    • 在 OutInActivity 中 使用 RecyclerView的适配器,添加数据生成列表

      import androidx.appcompat.app.AppCompatActivity;
      import androidx.recyclerview.widget.LinearLayoutManager;
      import androidx.recyclerview.widget.RecyclerView;
      import android.app.Activity;
      import android.content.Intent;
      import android.os.Bundle;
      import android.view.View;
      import java.util.ArrayList;
      import java.util.List;
       // 部分涉及 项目包名 导入(没写出来)
       /**
      * @esc: 出入库明细页面
      * @Author: xiaozhao
      * @CreateDate: 2022-10-23 11:18
      */
      public class OutInActivity extends AppCompatActivity {
          private Activity myActivity;
          private RecyclerView setOutInPageR;
          private WareRecyclerViewAdapter myAdapter;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              myActivity = OutInActivity.this;
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_out_in);
              initView();
          }
          //初始页面 控件
          private void initView() {
              setOutInPageR = findViewById(R.id.OutIn_page_recyclerview);
              setOutInAdapter();
          }
      
          // 创建  RecyclerView 适配器
          private void setOutInAdapter() {
              //setOutInR.setLayoutManager(new LinearLayoutManager(myActivity)); //设置线性布局,//网格布局GridLayoutManager //瀑布流网格布局StaggeredGridLayoutManager
              LinearLayoutManager layoutManager = new LinearLayoutManager(myActivity, RecyclerView.VERTICAL, false);
              setOutInPageR.setLayoutManager(layoutManager);
              // 设置每一项 item 的分割线
              // setOutInPageR.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
              myAdapter = new WareRecyclerViewAdapter(myActivity, getArrayList(),1);
              setOutInPageR.setAdapter(myAdapter);
              //给每一项添加点击事件
              myAdapter.setItemOnClick(new WareRecyclerViewAdapter.myItemOnClick() {
                  @Override
                  public void onItemClick(int position) {
                      Toast.makeText(myActivity, "你单击了:"+position, Toast.LENGTH_SHORT).show();
                  }
              });
          }
          //模拟数据
          private List<TestData> getArrayList() {
              List<TestData> dataList = new ArrayList<>();
              dataList.add(new TestData(1, "测试内容物料名称1111", "1/只", "2022-10-11", "销售", "出库"));
              dataList.add(new TestData(2, "测试内容物料名称2222", "1/只", "2022-9-30", "客户维修", "出库"));
              dataList.add(new TestData(3, "测试内容物料名称33", "10/套", "2022-10-12", "加工组件", "入库"));
              dataList.add(new TestData(4, "测试内容物料名称4", "1008/张", "2022-10-11", "采购", "入库"));
              dataList.add(new TestData(5, "测试内容物料名称", "5/只", "2022-10-11", "损耗", "出库"));
              dataList.add(new TestData(6, "66768测试内容物料名称1111", "5/只", "2022-10-05", "损耗", "出库"));
              dataList.add(new TestData(7, "测试内容物料名称1111343", "5/只", "2022-10-01", "加工组件", "出库"));
              dataList.add(new TestData(8, "测试内容物料名称3431)", "5/只", "2022-10-10", "加工组件", "出库"));
              dataList.add(new TestData(9, "测试内容物料名称1111e", "5/只", "2022-10-12", "加工组件", "出库"));
              dataList.add(new TestData(10, "测试内容物料名称454", "30/台", "2022-10-15", "采购", "入库"));
              dataList.add(new TestData(11, "测试内容物料名称", "5/台", "2022-10-11", "补齐", "入库"));
              dataList.add(new TestData(12, "对对对", "5/台", "2022-08-11", "配件维修", "入库"));
              dataList.add(new TestData(13, "橙色粉色测试", "5/只", "2022-09-16", "生产", "出库"));
              dataList.add(new TestData(14, "测试内容二111", "5/只", "2022-09-11", "销售", "出库"));
              return dataList;
          }
      }
      

关于 RecyclerView 中的列表布局问题

RecyclerView 中的列表项由 LayoutManager 类负责排列。RecyclerView 库提供了三种布局管理器,用于处理最常见的布局情况:

LinearLayoutManager 线性布局:将各个项排列在一维列表中。

  /**
  * LinearLayoutManager线性布局的构造函数原型
  * @param context       当前的上下文对象, 用于获取资源.
  * @param orientation   布局方向. 设置成 RecyclerView.VERTICAL 或 RecyclerView.HORIZONTAL.
  * @param reverseLayout 当设置成 true 时, 布局会翻转, 从尾部开始头部结束.
  */
  public LinearLayoutManager(Context context, @RecyclerView.Orientation int orientation,boolean reverseLayout) {
      setOrientation(orientation);
      setReverseLayout(reverseLayout);
  }
  // LinearLayoutManager 线性布局的简单使用
  private LinearLayoutManager getLinearLayoutManager() {
      //设置线性布局
      LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false) {
          //禁止竖向滑动 RecyclerView 为垂直状态(VERTICAL)
          @Override
          public boolean canScrollVertically() {
              return false;
          }
          //禁止横向滑动 RecyclerView 为水平状态(HORIZONTAL) canScrollHorizontally
      };
      return layoutManager;
  }

GridLayoutManager 网格布局:将所有项排列在二维网格中:

如果网格垂直排列,GridLayoutManager 会尽量使每行中所有元素的宽度和高度相同,但不同的行可以有不同的高度。
如果网格水平排列,GridLayoutManager 会尽量使每列中所有元素的宽度和高度相同,但不同的列可以有不同的宽度。

/**
* GridLayoutManager 网格布局的构造函数原型 (其中一个)
* @param context      当前的上下文对象, 用于获取资源.
* @param spanCount    网格中的列数
*/
public GridLayoutManager(Context context, int spanCount) {
    super(context);
    setSpanCount(spanCount);
}
/**
* GridLayoutManager 网格布局的构造函数原型 (其中一个)
* @param context       当前的上下文对象, 用于获取资源.
* @param spanCount     网格中的列或行数  
* @param orientation   布局方向. 设置成 RecyclerView.VERTICAL 或 RecyclerView.HORIZONTAL.
* @param reverseLayout 当设置成 true 时, 布局会翻转, 从尾部开始头部结束.
*/
public GridLayoutManager(Context context, int spanCount, @RecyclerView.Orientation int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
    setSpanCount(spanCount);
}
//简单用法
  private GridLayoutManager getGridLayoutManager() {
      //设置线性布局//网格布局GridLayoutManager //瀑布流网格布局 StaggeredGridLayoutManager
      GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 2,RecyclerView.VERTICAL,false) {
          //禁止竖向滑动 RecyclerView 为垂直状态(VERTICAL)
          @Override
          public boolean canScrollVertically() {
              return false;
          }
          //禁止横向滑动 RecyclerView 为水平状态(HORIZONTAL) canScrollHorizontally
      };
      return gridLayoutManager;
  }

StaggeredGridLayoutManager 瀑布流网格布局

与 GridLayoutManager 类似,但不要求同一行中的列表项具有相同的高度(垂直网格有此要求)或同一列中的列表项具有相同的宽度(水平网格有此要求)。其结果是,同一行或同一列中的列表项可能会错落不齐。

/**
* StaggeredGridLayoutManager 瀑布流网格布局的构造函数原型 (其中一个)
* @param spanCount    如果方向是垂直的,则spanCount是列数。 如果方向是水平的,则spanCount是行数。
* @param orientation  布局方向. 设置成 StaggeredGridLayoutManager.VERTICAL 或 StaggeredGridLayoutManager.HORIZONTAL.
*/
public StaggeredGridLayoutManager(int spanCount, int orientation) {
    mOrientation = orientation;
    setSpanCount(spanCount);
    mLayoutState = new LayoutState();
    createOrientationHelpers();
}
// 瀑布流网格布局 布局简单用法
  private StaggeredGridLayoutManager getStaggeredGridLayoutManager() {
      StaggeredGridLayoutManager gridLayoutManager = new  StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL) {
          @Override
          public boolean canScrollVertically() { //禁止垂直滚动
              return false;
          }
          //@Override
          //public boolean canScrollHorizontally() {return false;}//禁止水平滚动
      };
      return gridLayoutManager;
  }

来自:https://juejin.cn/post/7159197356758564894

相关文章

网友评论

      本文标题:Android 使用 RecyclerView 创建动态列表

      本文链接:https://www.haomeiwen.com/subject/fpnvtdtx.html