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
相关产品推荐
相关产品推荐

