Android中嵌套多ListView的NestedScrollView无法滚动问题
解决NestedScrollView嵌套ListView无法滚动的问题
问题原因
你当前布局中,多个ListView嵌套在NestedScrollView里,这两个组件都自带滚动机制,会触发滚动事件冲突,导致无法正常滚动。同时ListView设置android:layout_height="wrap_content"时,会展开所有列表项,但NestedScrollView的滚动逻辑和ListView的触摸事件处理互相干扰,最终出现滚动失效的情况。
解决方案
方案一:用RecyclerView实现分组列表(推荐,符合Android最佳实践)
这种方式彻底避免嵌套滚动冲突,同时性能更优。
1. 添加RecyclerView依赖
在Module级别的build.gradle中添加依赖:
dependencies { implementation "androidx.recyclerview:recyclerview:1.3.2" }
2. 修改布局文件
替换原有嵌套结构,仅保留一个RecyclerView:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.home.HomeFragment"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/grouped_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:padding="10dp"/> </androidx.constraintlayout.widget.ConstraintLayout>
3. 创建数据模型
定义标题项和列表项两种类型:
sealed class GroupItem { data class Header(val title: String) : GroupItem() data class ListItem(val content: String) : GroupItem() }
4. 实现RecyclerView适配器
class GroupedAdapter(private val itemList: List<GroupItem>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { companion object { private const val TYPE_HEADER = 0 private const val TYPE_ITEM = 1 } override fun getItemViewType(position: Int): Int { return when (itemList[position]) { is GroupItem.Header -> TYPE_HEADER is GroupItem.ListItem -> TYPE_ITEM } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) return if (viewType == TYPE_HEADER) { val view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false) HeaderViewHolder(view) } else { val view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false) ItemViewHolder(view) } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { is HeaderViewHolder -> { val header = itemList[position] as GroupItem.Header holder.titleTextView.text = header.title holder.titleTextView.setTypeface(null, Typeface.BOLD) } is ItemViewHolder -> { val item = itemList[position] as GroupItem.ListItem holder.contentTextView.text = item.content } } } override fun getItemCount() = itemList.size class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val titleTextView: TextView = itemView.findViewById(android.R.id.text1) } class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val contentTextView: TextView = itemView.findViewById(android.R.id.text1) } }
5. 在Fragment中初始化数据和RecyclerView
class HomeFragment : Fragment() { private lateinit var recyclerView: RecyclerView override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_home, container, false) recyclerView = view.findViewById(R.id.grouped_recycler_view) recyclerView.layoutManager = LinearLayoutManager(context) // 构建分组数据 val sportsArray = resources.getStringArray(R.array.sports_array) val itemList = mutableListOf<GroupItem>() repeat(4) { index -> itemList.add(GroupItem.Header("Header ${index + 1}")) sportsArray.forEach { sport -> itemList.add(GroupItem.ListItem(sport)) } } recyclerView.adapter = GroupedAdapter(itemList) return view } }
方案二:临时修复现有布局(不推荐,仅适合小数据量场景)
如果暂时不想重构,可通过禁用ListView自身滚动解决冲突,但数据量大时会导致性能问题:
给每个ListView添加android:nestedScrollingEnabled="false"属性,示例:
<ListView android:id="@+id/list1" android:layout_width="match_parent" android:layout_height="wrap_content" android:entries="@array/sports_array" android:nestedScrollingEnabled="false" />
内容的提问来源于stack exchange,提问作者Bilal
相关产品推荐
相关产品推荐

