You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测DraggableScrollableSheet下拉状态?setState下extent判断失效

问题原因
  • 浮点数精度误差:拖拽回调返回的extent是实时计算的双精度浮点值,控制台打印显示为0.49是输出时做了长度截断,实际值通常是0.489999999997、0.490000000002这类接近值,直接用== 0.49判断几乎不可能命中。
  • 判断逻辑存在覆盖:两个独立的if判断没有互斥关系,就算extent真的等于0.49,第一个分支将scrolable设为true后,会立刻命中第二个extent <= 0.49的分支,把值改回false,这就是注释setState后变量也始终为false的直接原因。
  • 无差别setState导致重建异常:如果在每帧的拖拽回调里都调用setState,会高频触发组件树重建,打断拖拽手势的事件流转,反而导致extent计算出错、判断逻辑不生效。
可直接运行的修复代码
NotificationListener<DraggableScrollableNotification>(
  onNotification: (DraggableScrollableNotification DSNotification) {
    // 增加精度容差判断是否到达最大展开位,避免浮点数精度问题
    bool isReachMax = (DSNotification.maxExtent - DSNotification.extent).abs() < 0.001;
    bool newScrollableState = isReachMax;
    
    // 仅当状态实际变化时才触发更新,避免每帧重建干扰拖拽逻辑
    if (newScrollableState != scrolable) {
      setState(() {
        scrolable = newScrollableState;
      });
    }
    print(scrolable);
    return true;
  },
  child: DraggableScrollableSheet(
    controller: controller,
    initialChildSize: 0,
    minChildSize: 0.0,
    maxChildSize: 0.49,
    builder: (_, scrollController) {
      return Container(
        decoration: BoxDecoration(
            color: Colors.white,
            border: Border.all(color: Colors.transparent),
            borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(15),
                topRight: Radius.circular(15))),
        child: ListView(controller: scrollController, children: [
          nfController.myWidget,
        ]),
      );
    },
  ),
)
修复点说明
  • 浮点数判断保留0.001的精度容差,同时直接取回调自带的maxExtent做对比,后续修改maxChildSize参数时不需要同步调整判断逻辑。
  • 先计算最终要设置的状态值,仅当新值和当前存储值不一致时才调用setState,过滤掉大量无意义的高频重建。
  • 移除了重复的独立判断分支,从逻辑上避免状态值被后续逻辑覆盖的问题。

内容的提问来源于stack exchange,提问作者Abmb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:36:20