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

Flutter滚动指定距离后显示AppBar,折叠ExpansionTile触发构建报错如何解决

错误原因

ExpansionTile折叠/展开时会改变滚动视口的高度,同步触发ScrollNotification回调,此时Flutter正处于当前帧的布局/绘制流程中,直接调用_colorAnimation.animateTo()会触发新的重绘请求,和当前正在执行的帧流程冲突,因此抛出构建过程中调度新帧的异常。

解决方案

根据你的使用场景选择以下任意一种方案即可:

方案1:直接赋值更新控制器值(适配当前0 duration的场景)

你当前配置的_colorAnimation时长为0,不需要过渡动画效果,直接给控制器的value赋值即可,避免触发不必要的帧调度,同时增加边界判断和重入校验优化性能:

bool _scrollListener(ScrollNotification scrollInfo) {
    // 只处理垂直方向的滚动更新事件,减少不必要的触发
    if (scrollInfo is ScrollUpdateNotification && scrollInfo.metrics.axis == Axis.vertical) {
      // 计算目标值,限制在0~1的合法范围内避免越界
      final targetValue = (scrollInfo.metrics.pixels / 260).clamp(0.0, 1.0);
      // 仅当值发生变化时才更新,减少无效重绘
      if (_colorAnimation.value != targetValue) {
        _colorAnimation.value = targetValue;
      }
    }
    return true;
}

方案2:使用PostFrameCallback调度更新(适配需要过渡动画的场景)

如果后续需要给AppBar颜色变化增加过渡效果,不使用0时长配置,就把动画更新操作放到当前帧绘制完成后的回调中执行,避开当前帧的构建流程:

import 'package:flutter/scheduler.dart';

bool _scrollListener(ScrollNotification scrollInfo) {
    if (scrollInfo is ScrollUpdateNotification && scrollInfo.metrics.axis == Axis.vertical) {
      final targetValue = (scrollInfo.metrics.pixels / 260).clamp(0.0, 1.0);
      if (_colorAnimation.value != targetValue) {
        SchedulerBinding.instance.addPostFrameCallback((_) {
          // 执行前校验组件是否仍挂载,避免页面销毁后调用报错
          if (mounted) {
            _colorAnimation.animateTo(targetValue);
          }
        });
      }
    }
    return true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:06:05