If the screen transition animation is especially janky the first time you run the app, but then gets smoother if you run the transition back and forth a few times, this is a known problem that both the Flutter team and their counterparts within Android and iOS are working on. They have a suggestion for a workaround here: https://docs.flutter.dev/perf/shader , built on "warming up shaders", but since it only warms up the shaders on the specific device you're debugging on, I honestly feel it's like the programming equivalent of "sweeping it under the rug"... You won't see the problem on your device anymore, but it's still there on other devices!
I however found a workaround for this problem myself, which works surprisingly well! I actually push the janky page, wait a bit, and then pop it again, without the user knowing it! π Like this:
import 'login_screen.dart';
import 'register_screen.dart';
import 'home_screen.dart';
import 'loading_screen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
class WelcomeScreen extends StatefulWidget {
const WelcomeScreen(Key? key) : super(key: key);
@override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen> {
@override
void initState() {
super.initState();
warmUp();
}
Future warmUp() async {
// This silly function is needed to remove jank from the first run screen transition...
print('Running warmUp()');
await Firebase.initializeApp();
// If not using Firebase, you'll have to add some other delay here!
// Otherwise, you will get errors below for trying to push new screens
// while the first one is still building.
if (mounted) {
Navigator.push(context, MaterialPageRoute(builder: (context) => LoginScreen(popWhenDone: false)));
Navigator.push(context, MaterialPageRoute(builder: (context) => RegisterScreen(popWhenDone: false, userType: UserType.artist)));
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen()));
Navigator.push(context, MaterialPageRoute(builder: (context) => LoadingScreen())); // Shows a spinner
await Future.delayed(Duration(milliseconds: 1000));
if (mounted) {
Navigator.popUntil(context, (route) => route.isFirst);
}
}
}
@override
Widget build(BuildContext context) {
print('Building $runtimeType');
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MaterialButton(
child: const Text('Sign Up'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const RegisterScreen();
}));
},
),
MaterialButton(
child: const Text('Log In'),
onPressed: () async {
await Firebase.initializeApp(); // In case I remove the warmUp() later...
if (mounted) {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, a1, a2) {
return LoginScreen();
},
transitionsBuilder: (context, a1, a2, child) {
return child; // I want only a Hero animation between the screens, nothing else
},
transitionDuration: const Duration(milliseconds: 1000),
),
);
}
},
),
],
),
Expanded(
flex: 4,
child: Hero(tag: 'logoWText', child: Image(image: AssetImage(kImageLogoWText))),
),
],
),
),
);
}
}
This ads a second of waiting for the app to load, with a spinner showing, but I find that most times, the spinner barely has time to show anyway, and in any case, it is a much better user experience to wait a sec for the app to load than to experience jank during use!
Other tips
If your screen transitions are still janky, even if you have run them back and forth, then you probably need to trim the performance of the screens involved. Perhaps it is your build method that's too big, and has too many things going on in it? Maybe certain widgets get rebuilt many times during each build of the screen?
Check out these pieces of advice and see if it helps: https://docs.flutter.dev/perf/best-practices In any case, they should improve your app's performance in general. π
Edit: And check out this link, as provided by ch271828n in a comment below: https://github.com/fzyzcjy/flutter_smooth