A problem with AnimatedCrossFade
is that you must provide both children, even if only one of them is being displayed.
If one (or both) of those children is complex and heavy, this is not efficient.
I have tried to provide a Builder
as a child, like this:
AnimatedCrossFade(
firstChild: widget1,
secondChild: Builder(builder: widget2builder),
duration: const Duration(milliseconds: 500),
crossFadeState: toggle ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),
var widget2builder = (context) {
print("Building widget 2");
return Container(),
);
};
However, this prints Building widget 2
right away, even if the first widget is the one being displayed and thus widget 2 is not needed at all.
This is a complete, runnable example:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
bool toggle;
@override
void initState() {
super.initState();
toggle = true;
}
@override
Widget build(BuildContext context) {
var toggleButton = Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
child: const Text("Toggle"),
color: Colors.grey,
onPressed: () {
setState(() {
toggle = !toggle;
});
},
),
);
var widget1 = Container(
key: UniqueKey(),
color: Colors.blue,
width: 200.0,
child: const Text(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt "
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
"ullamco laboris nisi ut aliquip ex ea commodo consequat.",
),
);
var widget2builder = (context) {
print("Building widget 2.");
return Container(
key: UniqueKey(),
color: Colors.red,
width: 200.0,
child: const Text(
"I am ready for my closeup.",
),
);
};
return MaterialApp(
home: Material(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
toggleButton,
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text("Some text above."),
AnimatedCrossFade(
firstChild: widget1,
secondChild: Builder(builder: widget2builder),
duration: const Duration(milliseconds: 500),
crossFadeState: toggle ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),
const Text("Some text below."),
],
),
],
),
),
);
}
}
If you run this, you will see that Building widget 2
is printed to the console, but widget 1 is the one being displayed.
My questions:
Is there any reason why
AnimatedCrossFade
is building the widget it doesn't use?How can I prevent this problem and use
AnimatedCrossFade
efficiently?