如何用Kotlin实现支持有序多选、显示选择序号的RecyclerView?
用Kotlin实现有序多选的RecyclerView方案
核心思路
通过给列表项维护选中序号(未选中时为null),用一个有序列表记录选中项的顺序,点击时切换选中状态并自动调整后续项的序号,最终得到按选择顺序排列的数组。
1. 定义数据类
创建Place数据类,包含地点信息和选中序号字段:
data class Place( val id: Int, val name: String, var selectedOrder: Int? = null // 记录选中顺序,null表示未选中 )
2. 列表项布局(item_place.xml)
用圆形TextView显示选中序号,默认隐藏,选中后显示:
<?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:padding="16dp" android:orientation="horizontal" android:gravity="center_vertical"> <!-- 选中序号显示 --> <TextView android:id="@+id/tv_order" android:layout_width="32dp" android:layout_height="32dp" android:background="@drawable/order_circle" android:gravity="center" android:textColor="@android:color/white" android:textSize="16sp" android:visibility="gone"/> <!-- 地点名称 --> <TextView android:id="@+id/tv_place_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:textSize="18sp"/> </LinearLayout>
圆形背景(res/drawable/order_circle.xml)
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/teal_200"/> </shape>
3. 实现RecyclerView Adapter
处理点击事件、维护选中顺序、更新UI:
class PlaceAdapter( private val places: MutableList<Place>, private val onSelectedListUpdated: (List<Place>) -> Unit // 回调通知选中列表变化 ) : RecyclerView.Adapter<PlaceAdapter.PlaceViewHolder>() { // 按选择顺序存储选中的地点 private val selectedPlaces = mutableListOf<Place>() inner class PlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvOrder: TextView = itemView.findViewById(R.id.tv_order) val tvPlaceName: TextView = itemView.findViewById(R.id.tv_place_name) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaceViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_place, parent, false) return PlaceViewHolder(view) } override fun onBindViewHolder(holder: PlaceViewHolder, position: Int) { val place = places[position] holder.tvPlaceName.text = place.name // 更新序号显示 place.selectedOrder?.let { holder.tvOrder.visibility = View.VISIBLE holder.tvOrder.text = it.toString() } ?: run { holder.tvOrder.visibility = View.GONE } // 处理选中/取消选中逻辑 holder.itemView.setOnClickListener { if (place.selectedOrder != null) { // 取消选中:移除并重新排序后续项的序号 selectedPlaces.remove(place) place.selectedOrder = null selectedPlaces.forEachIndexed { index, selectedPlace -> selectedPlace.selectedOrder = index + 1 } notifyDataSetChanged() } else { // 添加选中:分配新序号并加入有序列表 place.selectedOrder = selectedPlaces.size + 1 selectedPlaces.add(place) notifyItemChanged(position) } // 把最新的有序选中列表传递给外部 onSelectedListUpdated(selectedPlaces.toList()) } } override fun getItemCount() = places.size }
4. 在Activity中使用
初始化RecyclerView,获取最终的有序选中列表:
class MainActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView private var orderedSelectedPlaces = listOf<Place>() // 存储最终选中的有序地点 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerView = findViewById(R.id.recyclerView) recyclerView.layoutManager = LinearLayoutManager(this) // 模拟测试数据 val testPlaces = mutableListOf( Place(1, "天安门广场"), Place(2, "故宫博物院"), Place(3, "颐和园"), Place(4, "八达岭长城"), Place(5, "天坛公园") ) val adapter = PlaceAdapter(testPlaces) { selectedList -> orderedSelectedPlaces = selectedList // 这里可以做后续导航逻辑,比如打印选中顺序 Log.d("SelectedOrder", orderedSelectedPlaces.joinToString { "${it.name}(序号:${it.selectedOrder})" }) } recyclerView.adapter = adapter } }
内容的提问来源于stack exchange,提问作者Юля Муравьева
相关产品推荐
相关产品推荐

