目录
- RecyclerView是什么
- 如何使用
- RecyclerView 涉及到的类
- LayoutManager
- 为Item设置不同的布局样式
- 制作拖动的RecyclerView
一、RecyclerView是什么
RecyclerView是Android支持库中的一个控件,用于在列表或网格形式展示大量数据。它是ListView的升级版,提供了更灵活、可定制化的方式来展示和管理数据。
二、如何使用
RecyclerView的使用步骤:
- 创建RecyclerView控件对象
- 设置适配器 : 一般是使用自定义的适配器 , 设置给 RecyclerView 对象 ;
- 创建适配器的布局文件
- 创建并设置布局管理器 : 可以使用预置的布局管理器 , 也可以自定义布局管理器 ;
(1)创建控件
<androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/home_rv_product"android:layout_width="1500dp"android:layout_height="800dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/>
(2)创建适配器
class HomeProductAdapter(var productList:ArrayList<HomeProductBean>): RecyclerView.Adapter<HomeProductAdapter.MyViewHolder>() {inner class MyViewHolder(view: View): RecyclerView.ViewHolder(view){}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val view = LayoutInflater.from(parent.context).inflate(R.layout.home_item_home_product,parent,false)return MyViewHolder(view)}override fun getItemCount(): Int {return productList.size}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {}
}
<?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"android:layout_width="200dp"android:layout_height="270dp"android:layout_marginRight="20dp"android:layout_marginBottom="20dp"android:background="@drawable/dingdian_imge_price_bg"><ImageViewandroid:id="@+id/iv_sugar"android:layout_width="150dp"android:layout_height="150dp"android:layout_centerHorizontal="true"android:layout_marginTop="28dp"android:src="@drawable/icon_coin"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/tv_name1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:text="蓝色棉花"android:textColor="#fa7698"android:textSize="22sp"android:textStyle="bold"android:layout_marginTop="10dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/iv_sugar" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"android:gravity="center"android:layout_marginTop="10dp"app:layout_constraintTop_toBottomOf="@+id/tv_name1"><ImageViewandroid:id="@+id/home_imageview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="5dp"android:src="@drawable/icon_coin" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:text="0.0"android:textColor="#fa7698"android:textSize="30sp"android:textStyle="bold"/></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>
(3)进行使用
class HomeFragment : BaseFragment<HomeFragmentHomeBinding, HomeFragmentVM>() {private val productList = ArrayList<HomeProductBean>()private var homeProductAdapter:HomeProductAdapter? = nulloverride fun HomeFragmentHomeBinding.initView() {//设置布局排列方式,默认垂直排列val gridLayoutManager: GridLayoutManager =GridLayoutManager(this@HomeFragment.context, 6, GridLayoutManager.VERTICAL, false)homeRvProduct.layoutManager = gridLayoutManager//设置adapterproductList.add(HomeProductBean(1,"asdf"))productList.add(HomeProductBean(1,"asdf"))productList.add(HomeProductBean(1,"asdf"))productList.add(HomeProductBean(1,"asdf"))productList.add(HomeProductBean(1,"asdf"))productList.add(HomeProductBean(1,"asdf"))productList.add(HomeProductBean(1,"asdf"))....homeProductAdapter = HomeProductAdapter(productList)homeRvProduct.adapter = homeProductAdaptertvTime.setOnLongClickListener {val findNavController = findNavController()findNavController.navigate(R.id.home_action_home_homefragment_to_home_userloginfragment)return@setOnLongClickListener true}}}
运行结果:
三、RecyclerView 涉及到的类
-
RecyclerView:是RecyclerView控件的核心类,用于展示和管理数据。它负责协调LayoutManager、Adapter和ItemAnimator之间的交互,并处理用户交互事件。
-
RecyclerView.Adapter:是RecyclerView的适配器类,负责将数据绑定到RecyclerView上。开发者需要继承该类并实现必要的方法,如创建ViewHolder、绑定数据等。
-
RecyclerView.ViewHolder:是RecyclerView中每个列表项或网格项的持有者类。它包含了对应项的视图以及与之相关的操作。通过重写Adapter的 onCreateViewHolder() 方法来创建ViewHolder。RecyclerView.Adapter 适配器 的 onBindViewHolder 方法中为其关联数据 ;
-
RecyclerView.LayoutManager:是RecyclerView的布局管理器类,负责决定子项的排列方式。Android提了一些默认的LayoutManager,如LinearLayoutManager(线性布局)、GridLayoutManager(网格布局)和StaggeredGridLayoutManager(瀑布流布局),也可以自定义LayoutManager。
-
RecyclerView.ItemDecoration:是RecyclerView的装饰器类,用于为列表项添加分割线或其他样式。开发者可以继承该类并实现相应的方法,然后通过RecyclerView的addItemDecoration方法添加装饰器。
【binding.rvX.addItemDecoration(new CustomDecoration(mContext, LinearLayoutManager.VERTICAL, 2));】这句代码的作用是在RecyclerView中添加一个自定义的装饰器,用于给列表项之间添加分割线,并指定分割线的宽度和方向。 -
RecyclerView.ItemAnimator:是RecyclerView的动画类,用于在插入、删除和移动列表项时添加过渡动画效果。Android提供了一些默认的ItemAnimator,如DefaultItemAnimator和SimpleItemAnimator,也可以自定义ItemAnimator。
四、LayoutManager
4.1 线性布局 LinearLayoutManager
使用代码创建 线性布局管理器 LinearLayoutManager
LinearLayoutManager(Context context, @RecyclerView.Orientation int orientation, boolean reverseLayout)
context:表示上下文对象,通常是Activity或Fragment的引用。
orientation:表示布局的方向,可以是RecyclerView.HORIZONTAL(水平方向)或RecyclerView.VERTICAL(垂直方向)。
reverseLayout:表示是否将布局进行反转。如果设置为true,则列表项会从尾部开始排列;如果设置为false,则列表项会从头部开始排列。
reverseLayout这个参数在某些情况下很有用,比如当需要实现类似聊天界面的消息列表时,可以将reverseLayout设置为true,使得新的消息始终显示在列表的底部。
LinearLayoutManager layoutManagerFirst = new LinearLayoutManager(mContext,RecyclerView.HORIZONTAL,true);advancedNewBinding.rvAdvancedFirst.setLayoutManager(layoutManagerFirst);
4.2 GridLayoutManager
使用代码创建 线性布局管理器 GridLayoutManager
GridLayoutManager (Context context, int spanCount, @RecyclerView.Orientation int orientation, boolean reverseLayout)
参数同LinearLayoutManager一样。
int spanCount : 网格布局行或列的个数.
GridLayoutManager layoutManager = new GridLayoutManager(mContext, 8, GridLayoutManager.HORIZONTAL, false);advancedBinding.rvPara.setLayoutManager(layoutManager);
五、为Item设置不同的布局样式
比如,有的item需要的是:
布局一:文本+输入框+按钮
布局二:按钮
@Overridepublic int getItemViewType(int position) {//这里为不同位置的组件设置不同的布局类型 ;if (position > 27) return TYPE_OTHER;return TYPE_NORMAL;}
@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {View inflate;//根据布局类型加载不同的布局文件if (viewType == TYPE_NORMAL) {inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_parameter_new, viewGroup, false);return new ViewHolder(inflate);} else {inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_manual_advanced, viewGroup, false);return new ViewHolderOther(inflate);}}
六、制作拖动的RecyclerView
比如我们想通过拖动item来调整位置,应该如何操作呢?
ItemTouchHelper 可以为 RecyclerView 添加拖动效果 ;
ItemTouchHelper 需要与 RecyclerView 和 ItemTouchHelper.Callback 结合起来使用 ;
ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() {//线性布局和网格布局都可以使用@Overridepublic int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {int dragFrlg = 0;if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {dragFrlg = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;} else if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {dragFrlg = ItemTouchHelper.UP | ItemTouchHelper.DOWN;}return makeMovementFlags(dragFrlg, 0);}@Overridepublic boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {//滑动事件 下面注释的代码,滑动后数据和条目错乱,被舍弃
// Collections.swap(datas,viewHolder.getAdapterPosition(),target.getAdapterPosition());
// ap.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());//得到当拖拽的viewHolder的Positionint fromPosition = viewHolder.getAdapterPosition();//拿到当前拖拽到的item的viewHolderint toPosition = target.getAdapterPosition();if (fromPosition < toPosition) {for (int i = fromPosition; i < toPosition; i++) {Collections.swap(showAdapter.getGoodsBeans(), i, i + 1);}} else {for (int i = fromPosition; i > toPosition; i--) {Collections.swap(showAdapter.getGoodsBeans(), i, i - 1);}}showAdapter.notifyItemMoved(fromPosition, toPosition);return true;}@Overridepublic void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {//侧滑删除可以使用;}@Overridepublic boolean isLongPressDragEnabled() {//启用长按拖动功能return true;}/*** 长按选中Item的时候开始调用* 长按高亮** @param viewHolder* @param actionState*/@SuppressLint("MissingPermission")@Overridepublic void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {super.onSelectedChanged(viewHolder, actionState);if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {viewHolder.itemView.setScaleX(1.1f);viewHolder.itemView.setScaleY(1.1f);}}/*** 手指松开的时候还原高亮** @param recyclerView* @param viewHolder*/@Overridepublic void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {super.clearView(recyclerView, viewHolder);viewHolder.itemView.setBackgroundColor(0);showAdapter.notifyDataSetChanged(); //完成拖动后刷新适配器,这样拖动后删除就不会错乱}});//为rv设置helperhelper.attachToRecyclerView(binding.rvShow);