iTranslated by AI
Managing Screen Orientation on a Per-Screen Basis in Flutter
While I have some doubts about whether changing whether rotation is possible or not on a per-screen basis is good for usability, I've confirmed it works on both iOS and Android, so I'll leave a note here.
Steps
Native Project Settings
In the native settings for iOS and Android, allow all orientations for screen rotation.
By default, all orientations should be allowed, so if you haven't made any specific changes, no action is required.
Flutter Implementation
Add a class for monitoring screen transitions to navigatorObservers in MaterialApp. Within this class, check the destination screen and change the allowed orientation settings for each rotation.
class RootApp extends StatelessWidget {
const RootApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const HomeScreeen(),
navigatorObservers: [
// Class for monitoring screen transitions
MyNavigatorObserver(),
],
);
}
}
Implement the class for monitoring screen transitions as follows:
class MyNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route route, Route? previousRoute) {
// When navigating to a new screen
super.didPush(route, previousRoute);
if (route.settings.name == RotatableScreen.name) {
// For screens that allow rotation
SystemChrome.setPreferredOrientations([
// Register portrait and landscape as allowed orientations
DeviceOrientation.portraitUp,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
} else {
// For screens that do not allow rotation
SystemChrome.setPreferredOrientations([
// Register only portrait as the allowed orientation
DeviceOrientation.portraitUp,
]);
}
}
@override
void didPop(Route route, Route? previousRoute) {
// When returning to the previous screen
super.didPop(route, previousRoute);
if (route.settings.name == RotatableScreen.name) {
// For screens that allow rotation
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
} else {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
}
}
}
There are various ways to determine whether or not a screen is a target for allowing rotation. In the example above, I use the value set in RouteSettings.name for the determination, assuming that a unique string is assigned to it when calling Navigator.push during screen transitions.
// Screen transition process
Navigator.push<void>(context, RotatableScreen.route());
// RotatableScreen
class RotatableScreen extends StatelessWidget {
const RotatableScreen({Key? key}) : super(key: key);
static const name = 'RotatableScreen';
static MaterialPageRoute route() => MaterialPageRoute<RotatableScreen>(
builder: (_) => const RotatableScreen(),
settings: const RouteSettings(name: name),
);
@override
Widget build(BuildContext context) {
// ...
Discussion