-
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;
}
网友评论