Flutter开发listview嵌套滑动冲突问题

本文介绍了在Flutter开发中遇到的ListView嵌套滑动冲突及自适应高度问题。通过设置ListView的`shrinkWrap`为true和`physics`为`NeverScrollableScrollPhysics()`,可以避免滑动冲突并实现内容自适应高度。同时,提供了完整的代码示例来解决这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

最近在使用Flutter进行业务开发,使用fish-redux进行页面开发中使用了ListView的嵌套,在滑动中会导致竖向滑动冲突。
另外还有个问题, listview在使用的时候需要给个高度, 如果需要根据内容显示自适应高度,也需要进行处理,否则就无法展示list列表内容。

知识点

解决以上两个问题主要用到了Flutter组件Listview的两个属性,分别是:

ScrollPhysics physics,
bool shrinkWrap = false,
shrinkWrap

先说这个字段,默认是flase,就是说listview在使用的过程中,需要指定一个固定高度值,或者占据最大高度, 必须要有个边界范围,否则内容无法展示,在listview的源码中也有相关解释。

/// Whether the extent of the scroll view in the [scrollDirection] should be
  /// determined by the contents being viewed.
  ///
  /// If the scroll view does not shrink wrap, then the scroll view will expand
  /// to the maximum allowed size in the [scrollDirection]. If the scroll view
  /// has unbounded constraints in the [scrollDirection], then [shrinkWrap] must
  /// be true.
  ///
  /// Shrink wrapping the content of the scroll view is significantly more
  /// expensive than expanding to the maximum allowed size because the content
  /// can expand and contract during scrolling, which means the size of the
  /// scroll view needs to be recomputed whenever the scroll position changes.
  ///
  /// Defaults to false.
physics

这个字段表示用户在list上的滑动响应,通常情况下,内容不足设置高度时,没有滑动效果,这也是通常设计。

在我们的场景中, listview的列表项中也有一个子列表,同方向上如果子列表响应了滑动,就会导致父列表无法响应滑动手势了,导致滑动冲突了,这肯定不是我们想要的。
通过设置子列表的physics属性值为NeverScrollableScrollPhysics(), 跟随父列表的滑动响应。

physics: NeverScrollableScrollPhysics(), // 禁用滑动事件

以下是NeverScrollableScrollPhysics的源码, 它是ScrollPhysics的一个子类。

class NeverScrollableScrollPhysics extends ScrollPhysics {
  /// Creates scroll physics that does not let the user scroll.
  const NeverScrollableScrollPhysics({ ScrollPhysics parent }) : super(parent: parent);

  @override
  NeverScrollableScrollPhysics applyTo(ScrollPhysics ancestor) {
    return NeverScrollableScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  bool shouldAcceptUserOffset(ScrollMetrics position) => false;

  @override
  bool get allowImplicitScrolling => false;
}

通过第二行的注释 也能看出来, 禁止用户滑动。

完整代码展示(子列表)

ListView.builder(
              physics: NeverScrollableScrollPhysics(), // 禁用滑动事件
              shrinkWrap: true, //解决无限高度
              itemCount: bonusList.length,
              itemExtent: 30.0, //强制高度为50.0
              itemBuilder: (BuildContext context, int index) {
                return itemView(itemData);
              })

通过以上代码设置就能很好的解决listview嵌套滑动导致的冲突问题。

觉得文章不错的,给我点个赞哇,关注一下呗!
技术交流可关注公众号【君伟说】,回复“技术交流”,加我好友一起探讨

### 解决方案 在 Flutter 中,`ListView` 嵌套可能会导致 `easy_refresh` 插件的下拉刷新功能被误触发。这是因为外层和内层的滚动视图可能同时响应用户的滑动手势[^2]。 为了避免这种情况的发生,可以通过禁用内部 `ListView` 的滚动行为来解决问题。具体来说,设置 `physics: NeverScrollablePhysics()` 可以让内部的 `ListView` 不再独立处理滑动事件,从而避免与外部的 `easy_refresh` 发生冲突。 以下是完整的解决方案代码: ```dart import 'package:flutter/material.dart'; import 'package:easy_refresh/easy_refresh.dart'; class NestedListExample extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: EasyRefresh( onRefresh: () async { // 处理下拉刷新逻辑 await Future.delayed(Duration(seconds: 2)); }, onLoad: () async { // 处理上拉加载更多逻辑 await Future.delayed(Duration(seconds: 2)); }, child: ListView.builder( itemCount: 3, // 假设有三个子列表 itemBuilder: (context, index) { return Container( height: 200, child: ListView.builder( physics: NeverScrollablePhysics(), // 关键:禁用内部 ListView 滚动 shrinkWrap: true, // 自适应高度 itemCount: 10, itemBuilder: (context, subIndex) { return ListTile( title: Text('Item $subIndex in List $index'), ); }, ), ); }, ), ), ); } } ``` 上述代码通过以下方式解决了嵌套问题: - 设置 `NeverScrollablePhysics()` 来禁用内部 `ListView` 的滚动能力。 - 使用 `shrinkWrap: true` 让内部 `ListView` 能够自动调整其大小,以便更好地适配父级容器的高度。 此外,如果需要更复杂的交互体验或者自定义样式,可以参考 `easy_refresh` 提供的内置样式或创建自己的样式[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值