当前位置: 首页 > web >正文

安卓开饭-ScrollView内嵌套了多个RecyclerView,只想与其中一个RecyclerView有联动

在 Android 开发中,将 RecyclerView 嵌套在 ScrollView 内通常会导致性能问题和滚动冲突,应尽量避免这种设计。以下是原因和替代方案:

为什么不推荐 RecyclerView + ScrollView?​​
  • 性能损耗​
    RecyclerView 本身已自带高效回收复用机制,嵌套在 ScrollView 中会强制 RecyclerView 一次性加载所有子项(失去回收优势),导致内存和渲染性能下降。
  • 滚动冲突​
    内层 RecyclerView 和外层 ScrollView 会竞争触摸事件,导致滚动不流畅或无法滚动。
  • 测量问题
    ScrollView 要求子视图有固定高度,而 RecyclerView 的高度是动态计算的,可能导致布局错乱。

核心思路​

  • ​禁用不需要联动的 RecyclerView 的滚动​
    通过 setNestedScrollingEnabled(false) 或 XML 属性让特定 RecyclerView 不响应外部 ScrollView 的滚动事件。
  • ​动态控制滚动行为​
    通过 OnScrollListener 或自定义 NestedScrollingParent 协调滚动逻辑。

XML配置

<androidx.recyclerview.widget.RecyclerViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:nestedScrollingEnabled="false" />  <!-- 关键:禁止联动 -->

代码配置

// 禁止 RecyclerView1 联动
recyclerView1.isNestedScrollingEnabled = false// 允许 RecyclerView2 联动
recyclerView2.isNestedScrollingEnabled = true

ListView时期古老的方案- 自定义ListView 让其直接平铺

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;public class ScrollDisabledListView extends ListView {private int mPosition;public ScrollDisabledListView(Context context) {super(context);}public ScrollDisabledListView(Context context, AttributeSet attrs) {super(context, attrs);}public ScrollDisabledListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;if (actionMasked == MotionEvent.ACTION_DOWN) {// 记录手指按下时的位置mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());return super.dispatchTouchEvent(ev);}if (actionMasked == MotionEvent.ACTION_MOVE) {// 最关键的地方,忽略MOVE 事件// ListView onTouch获取不到MOVE事件所以不会发生滚动处理return true;}// 手指抬起时if (actionMasked == MotionEvent.ACTION_UP|| actionMasked == MotionEvent.ACTION_CANCEL) {// 手指按下与抬起都在同一个视图内,交给父控件处理,这是一个点击事件if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {super.dispatchTouchEvent(ev);} else {// 如果手指已经移出按下时的Item,说明是滚动行为,清理Item pressed状态setPressed(false);invalidate();return true;}}return super.dispatchTouchEvent(ev);}
}
http://www.xdnf.cn/news/6263.html

相关文章:

  • Kite AI 自动机器人部署教程
  • 使用深度学习预训练模型检测物体
  • MQTT 在Spring Boot 中的使用
  • 第二章 变量和运算符
  • C++取时间戳窗口
  • 在线黑白图像转换:简单却强大的视觉表达工具
  • 计算机组成原理:I/O
  • 死信队列-常见的业务场景
  • gd32e230c8t6 keil6工程模板
  • 关于嵌入式系统的知识课堂(一)
  • 2天长沙旅游规划
  • 几种运放典型应用电路
  • Vue:显示数据
  • HTML 颜色全解析:从命名规则到 RGBA/HSL 值,附透明度设置与场景应用指南
  • Flutter - UIKit开发相关指南 - 线程和异步
  • Seed1.5-VL:高效通用的视觉-语言基础模型
  • leetcode - 滑动窗口问题集
  • Qt 自定义槽 + 自定义信号(9)
  • 《数据库原理》部分习题解析1
  • 使用Haproxy搭建高效Web群集的完整指南
  • MATLAB中heatmap函数
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的低集中度市场运营策略研究
  • RHCE认证通过率
  • LeetCode Hot100 (1/100)
  • 家庭宽带的内网穿透实践
  • 数学实验(Matlab符号运算)
  • 面试篇: Redis(持续更新)
  • vue3基础学习 [简单标签] (vscode)
  • More Effective C++:改善编程与设计(上)
  • Redis内存淘汰策略和过期键删除策略有哪些?