Home > Back-end >  Trigger a device orientation change when screen is removed from Navigation stack (ie user goes "
Trigger a device orientation change when screen is removed from Navigation stack (ie user goes "

Time:09-16

This app sets the device orientation to portrait within main():

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations(
    [DeviceOrientation.portraitUp],
  ).then((_) {
    runApp(const MyApp());
  });
}

One screen is a slideshow, which is set to landscape:

SystemChrome.setPreferredOrientations([
  DeviceOrientation.landscapeLeft,
  DeviceOrientation.landscapeRight,
]);
return MaterialApp(
  ...
);

The problem is when the user returns from the slideshow to the "Main Screen", the orientation does not switch again. However if the screen is pushed onto the Navigation stack, the orientation changes as expected.

Current Flow

  • Splash (Portrait)
  • Main Screen (Portrait)
  • Slideshow (Landscape)
  • Main Screen, back from Slideshow (still Landscape) <<- this should trigger portrait again!
  • Splash (still Landscape)
  • Forward to Main Screen <<- now this re-triggers the orientation change

How can the orientation be re-triggered when screens are popped (removed) from the navigation stack?

Edit

I should also note, I've tried to add a trigger to the main screen, but this has no effect:

class MainScreen extends StatelessWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
  ...

CodePudding user response:

Here are 3 ways how you can set your orientation back to portrait when you navigate back:

You wrap your landscape widget with a WillPopScope and call setPreferredOrientations inside onWillPop:

return WillPopScope(
      onWillPop: () {
        SystemChrome.setPreferredOrientations(
          [DeviceOrientation.portraitUp],
        );
        return Future.value(true);
      },
      child: Container(
        color: Colors.red,
      ),
    );

You make your second widget stateful and call setPreferredOrientations in dispose:

@override
  void dispose() {
    SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp],
    );
    super.dispose();
  }

You await the Navigator.push or Navigator.pushNamed call and do the orientation change after returning back from the second screen:

await Navigator.push(
        context, MaterialPageRoute(builder: (context) => SecondPage()));
    SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp],
    );
  • Related