目录
- RecyclerView是什么
- 如何使用
- RecyclerView 涉及到的类
- LayoutManager
- 为Item设置不同的布局样式
- 制作拖动的RecyclerView
一、RecyclerView是什么
RecyclerView是Android支持库中的一个控件,用于在列表或网格形式展示大量数据。它是ListView的升级版,提供了更灵活、可定制化的方式来展示和管理数据。
二、如何使用
RecyclerView的使用步骤:
- 创建RecyclerView控件对象
- 设置适配器 : 一般是使用自定义的适配器 , 设置给 RecyclerView 对象 ;
- 创建适配器的布局文件
- 创建并设置布局管理器 : 可以使用预置的布局管理器 , 也可以自定义布局管理器 ;
(1)创建控件
<androidx.recyclerview.widget.RecyclerView
android: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">
<ImageView
android: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" />
<TextView
android: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" />
<LinearLayout
android: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">
<ImageView
android:id="@+id/home_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:src="@drawable/icon_coin" />
<TextView
android: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? = null
override fun HomeFragmentHomeBinding.initView() {
//设置布局排列方式,默认垂直排列
val gridLayoutManager: GridLayoutManager =
GridLayoutManager(this@HomeFragment.context, 6, GridLayoutManager.VERTICAL, false)
homeRvProduct.layoutManager = gridLayoutManager
//设置adapter
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"))
productList.add(HomeProductBean(1,"asdf"))
....
homeProductAdapter = HomeProductAdapter(productList)
homeRvProduct.adapter = homeProductAdapter
tvTime.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需要的是:
布局一:文本+输入框+按钮
布局二:按钮
@Override
public int getItemViewType(int position) {
//这里为不同位置的组件设置不同的布局类型 ;
if (position > 27) return TYPE_OTHER;
return TYPE_NORMAL;
}
@Override
public 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() {
//线性布局和网格布局都可以使用
@Override
public 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);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//滑动事件 下面注释的代码,滑动后数据和条目错乱,被舍弃
// Collections.swap(datas,viewHolder.getAdapterPosition(),target.getAdapterPosition());
// ap.notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
//得到当拖拽的viewHolder的Position
int fromPosition = viewHolder.getAdapterPosition();
//拿到当前拖拽到的item的viewHolder
int 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;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//侧滑删除可以使用;
}
@Override
public boolean isLongPressDragEnabled() {
//启用长按拖动功能
return true;
}
/**
* 长按选中Item的时候开始调用
* 长按高亮
*
* @param viewHolder
* @param actionState
*/
@SuppressLint("MissingPermission")
@Override
public 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
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setBackgroundColor(0);
showAdapter.notifyDataSetChanged(); //完成拖动后刷新适配器,这样拖动后删除就不会错乱
}
});
//为rv设置helper
helper.attachToRecyclerView(binding.rvShow);