Rebuilding BottomNavigationBar when items.length changes (#19179)
This commit is contained in:
parent
032f8cdb8b
commit
8b5cbca765
@ -303,7 +303,7 @@ class _BottomNavigationTile extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerProviderStateMixin {
|
||||
List<AnimationController> _controllers;
|
||||
List<AnimationController> _controllers = <AnimationController>[];
|
||||
List<CurvedAnimation> _animations;
|
||||
|
||||
// A queue of color splashes currently being animated.
|
||||
@ -315,9 +315,13 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
|
||||
|
||||
static final Tween<double> _flexTween = new Tween<double>(begin: 1.0, end: 1.5);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
void _resetState() {
|
||||
for (AnimationController controller in _controllers)
|
||||
controller.dispose();
|
||||
for (_Circle circle in _circles)
|
||||
circle.dispose();
|
||||
_circles.clear();
|
||||
|
||||
_controllers = new List<AnimationController>.generate(widget.items.length, (int index) {
|
||||
return new AnimationController(
|
||||
duration: kThemeAnimationDuration,
|
||||
@ -335,6 +339,12 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
|
||||
_backgroundColor = widget.items[widget.currentIndex].backgroundColor;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_resetState();
|
||||
}
|
||||
|
||||
void _rebuild() {
|
||||
setState(() {
|
||||
// Rebuilding when any of the controllers tick, i.e. when the items are
|
||||
@ -385,6 +395,13 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
|
||||
@override
|
||||
void didUpdateWidget(BottomNavigationBar oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
// No animated segue if the length of the items list changes.
|
||||
if (widget.items.length != oldWidget.items.length) {
|
||||
_resetState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget.currentIndex != oldWidget.currentIndex) {
|
||||
switch (widget.type) {
|
||||
case BottomNavigationBarType.fixed:
|
||||
|
@ -602,6 +602,44 @@ void main() {
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('BottomNavigationBar handles items.length changes', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/10322
|
||||
|
||||
Widget buildFrame(int itemCount) {
|
||||
return new MaterialApp(
|
||||
home: new Scaffold(
|
||||
bottomNavigationBar: new BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
currentIndex: 0,
|
||||
items: new List<BottomNavigationBarItem>.generate(itemCount, (int itemIndex) {
|
||||
return new BottomNavigationBarItem(
|
||||
icon: const Icon(Icons.android),
|
||||
title: new Text('item $itemIndex'),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildFrame(3));
|
||||
expect(find.text('item 0'), findsOneWidget);
|
||||
expect(find.text('item 1'), findsOneWidget);
|
||||
expect(find.text('item 2'), findsOneWidget);
|
||||
expect(find.text('item 3'), findsNothing);
|
||||
|
||||
await tester.pumpWidget(buildFrame(4));
|
||||
expect(find.text('item 0'), findsOneWidget);
|
||||
expect(find.text('item 1'), findsOneWidget);
|
||||
expect(find.text('item 2'), findsOneWidget);
|
||||
expect(find.text('item 3'), findsOneWidget);
|
||||
|
||||
await tester.pumpWidget(buildFrame(2));
|
||||
expect(find.text('item 0'), findsOneWidget);
|
||||
expect(find.text('item 1'), findsOneWidget);
|
||||
expect(find.text('item 2'), findsNothing);
|
||||
expect(find.text('item 3'), findsNothing);
|
||||
});
|
||||
}
|
||||
|
||||
Widget boilerplate({ Widget bottomNavigationBar, @required TextDirection textDirection }) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user