我有一个StatefullWidget,其中包含一个脚手架,其主体中的Scrollview,一个BottomAppBar,其凹口包含一个FloatingActionButton。
随机滚动时,会引发以下断言错误:
I/flutter (29780): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (29780): The following assertion was thrown during performLayout():
I/flutter (29780): 'package:flutter/src/material/scaffold.dart': Failed assertion: line 423 pos 16: 'bodyMaxHeight <=
I/flutter (29780): math.max(0.0, looseConstraints.maxHeight - contentTop)': is not true.
I/flutter (29780):
I/flutter (29780): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (29780): more information in this error message to help you determine and fix the underlying cause.
I/flutter (29780): In either case, please report this assertion by filing a bug on GitHub:
I/flutter (29780): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter (29780):
I/flutter (29780): When the exception was thrown, this was the stack:
I/flutter (29780): #2 _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:423:16)
I/flutter (29780): #3 MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:212:7)
I/flutter (29780): #4 RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:356:14)
I/flutter (29780): #5 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1519:7)
I/flutter (29780): #6 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:766:18)
I/flutter (29780): #7 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:347:19)
I/flutter (29780): #8 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
I/flutter (29780): #9 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:286:5)
I/flutter (29780): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1012:15)
I/flutter (29780): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:952:9)
I/flutter (29780): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:864:5)
I/flutter (29780): #16 _invoke (dart:ui/hooks.dart:219:10)
I/flutter (29780): #17 _drawFrame (dart:ui/hooks.dart:178:3)
I/flutter (29780): (elided 5 frames from class _AssertionError and package dart:async)
I/flutter (29780):
I/flutter (29780): The following RenderObject was being processed when the exception was fired:
I/flutter (29780): RenderCustomMultiChildLayoutBox#0211b NEEDS-LAYOUT NEEDS-PAINT
I/flutter (29780): creator: CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ←
I/flutter (29780): _InkFeatures-[GlobalKey#fe169 ink renderer] ← NotificationListener<LayoutChangedNotification> ←
I/flutter (29780): PhysicalModel ← AnimatedPhysicalModel ← Material ← PrimaryScrollController ← _ScaffoldScope ←
I/flutter (29780): Scaffold ← ⋯
I/flutter (29780): parentData: <none> (can use size)
I/flutter (29780): constraints: BoxConstraints(w=411.4, h=683.4)
I/flutter (29780): size: Size(411.4, 683.4)
I/flutter (29780): This RenderObject had the following descendants (showing up to depth 5):
I/flutter (29780): _RenderLayoutBuilder#c4759 relayoutBoundary=up1
I/flutter (29780): RenderConstrainedBox#f3db9 relayoutBoundary=up2
I/flutter (29780): RenderRepaintBoundary#7768d NEEDS-PAINT
I/flutter (29780): RenderCustomPaint#4fd8f NEEDS-PAINT
I/flutter (29780): RenderRepaintBoundary#3b2ce
I/flutter (29780): RenderConstrainedBox#f158f relayoutBoundary=up1 NEEDS-PAINT
I/flutter (29780): RenderPhysicalShape#9331d NEEDS-PAINT
I/flutter (29780): RenderCustomPaint#26663 NEEDS-PAINT
I/flutter (29780): _RenderInkFeatures#a489b NEEDS-PAINT
I/flutter (29780): RenderPadding#db65e NEEDS-PAINT
I/flutter (29780): RenderStack#80cab relayoutBoundary=up1
I/flutter (29780): RenderTransform#033b9 relayoutBoundary=up2
I/flutter (29780): RenderTransform#b621a relayoutBoundary=up3
I/flutter (29780): RenderSemanticsAnnotations#56fe9 relayoutBoundary=up4
I/flutter (29780): _RenderInputPadding#e9ac7 relayoutBoundary=up5
I/flutter (29780): ════════════════════════════════════════════════════════════════════════════════════════════════════
因为我们使用的是带有凹口和FloatingActionButton(FAB)的BottomAppBar,所以我们希望FAB后面的区域(形成凹口)是透明的,因为我们在滚动的帮助下将BottomAppBar隐藏在了一个AnimatedContainer。因此,我们在脚手架中将以下标志设置为true:
extendBody: true
删除此标志时,不再发生错误,但是如上所述,这不是我们的选择。
我们创建了一个示例代码以尽可能小的规模复制错误:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
ScrollController _scrollController;
bool _visible = true;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(() {
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
setState(() {
_visible = false;
});
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
setState(() {
_visible = true;
});
}
});
}
@override
Widget build(BuildContext context) {
double _bottomAppBarHeight = MediaQuery.of(context).size.width * 0.1;
return Scaffold(
extendBody: true,
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: <Widget>[
Text('Top'),
Container(
color: Colors.red,
height: MediaQuery.of(context).size.height,
),
Text('Bottom'),
],
),
),
),
bottomNavigationBar: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.linear,
height: _visible ? _bottomAppBarHeight : 0.0,
child: BottomAppBar(
color: Colors.green,
shape: CircularNotchedRectangle(),
child: IconButton(
onPressed: () {},
icon: Icon(Icons.menu),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
我们当前的flutter版本是:
Flutter (Channel stable, v1.5.4-hotfix.2, on Microsoft Windows [Version 10.0.17134.799], locale de-DE)
这实际上是抖动本身的问题,还是我们只是缺少了一些重要的东西?
更新
我们在GitHub上的flutter仓库中创建了一个问题:https://github.com/flutter/flutter/issues/34326