Flutter: how to prevent device orientation changes and force portrait?

149,163

Solution 1

Import package:flutter/services.dart, then

Put the SystemChrome.setPreferredOrientations inside the Widget build() method.

Example:

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
      ]);
      return new MaterialApp(...);
    }
  }

Update

This solution mightn't work for some IOS devices as mentioned in the updated flutter documentation on Oct 2019.

They Advise to fixed the orientation by setting UISupportedInterfaceOrientations in Info.plist like this

<array>
    <string>UIInterfaceOrientationPortrait</string>
</array>

For more information https://github.com/flutter/flutter/issues/27235#issuecomment-508995063

Solution 2

@boeledi, If you want to “lock” the device orientation and not allow it to change as the user rotates their phone, this was easily set as below,

// This did not work as requirement
void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  runApp(new MyApp());
}

You have to wait until setPreferredOrientations is done and then start the app

// This will works always for lock screen Orientation.
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}

Solution 3

iOS:

Calling SystemChrome.setPreferredOrientations() doesn't work for me, and I had to change the Device Orientation in the Xcode project as following:

enter image description here

Android:

Set the screenOrientation attribute to portrait for the main activity in the file android/app/src/main/AndroidManifest.xml as following:

enter image description here

Solution 4

Put the WidgetsFlutterBinding.ensureInitialized() else you will get an error while building.

import 'package:flutter/services.dart';

    void main() async => {
          WidgetsFlutterBinding.ensureInitialized();
          await SystemChrome.setPreferredOrientations(
              [DeviceOrientation.portraitUp],
          ); // To turn off landscape mode
          runApp(MainApp());
        };

Solution 5

Open android/app/src/main/AndroidManifest.xml and add the following line in the MainActivity:

android:screenOrientation="portrait"

If you have this:

<activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize">

You should end up with something like this:

<activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize">

This works for Android. On iOS, you will have to change this from the Xcode page: https://i.stack.imgur.com/hswoe.png (as Hejazi said)

Share:
149,163

Related videos on Youtube

boeledi
Author by

boeledi

Updated on December 26, 2021

Comments

  • boeledi
    boeledi over 2 years

    I would like to prevent my application from changing its orientation and force the layout to stick to "portrait".

    In the main.dart, I put:

    void main(){
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown
      ]);
      runApp(new MyApp());
    }
    

    but when I use the Android Simulator rotate buttons, the layout "follows" the new device orientation...

    How could I solve this?

    Thanks

    • Brian Kung
      Brian Kung about 6 years
      Assuming you imported 'package:flutter/services.dart', then maybe it's a bug: github.com/flutter/flutter/issues/13238
    • Hemanth Raj
      Hemanth Raj about 6 years
      Not sure why this happens to you. I tried running your code on an emulator and also my own device and it works fine.
    • user3162901
      user3162901 about 4 years
      SystemChrome.setPreferredOrientations returns asynchronously, so seems like runApp should be enclosed in a then.
  • Boy
    Boy over 4 years
    I had the same problem, did you run it on an iPad? I only tested on an iPad and this seems to be an issue: github.com/flutter/flutter/issues/27235
  • Rob Lyndon
    Rob Lyndon over 4 years
    I strongly disagree. await is a ubiquitous programming pattern that is present in multiple languages, and it's very clear what expressive. then creates levels of nesting. If you have three or four continuations, then starts to become very difficult to read indeed.
  • Mateus Felipe
    Mateus Felipe over 4 years
    .then can be chained instead of nesting, as it expects a FutureOr. This allows me to use a more functional approach, which is more readable and elegant. For example, I can use expression body instead of bracketed body by chaining the "thens".
  • Tincho825
    Tincho825 about 4 years
    It sometimes throws an error while compiling, you should use native solutions. Adding 'android:screenOrientation="portrait"' to MainActivity on AndroidManifest as Abeer Iqbal's suggests worked for me on Android.
  • Tincho825
    Tincho825 about 4 years
    It sometimes throws an error while compiling, you should use native solutions. Adding 'android:screenOrientation="portrait"' to MainActivity on AndroidManifest as Abeer Iqbal's suggests worked for me on Android.
  • MR_AMDEV
    MR_AMDEV about 4 years
    thanks ,REMEMBER the order of "portrait" after the configChanges "orientation" does matter.
  • BIS Tech
    BIS Tech about 4 years
    android: This attribute was added in API level 24.
  • Ryan
    Ryan almost 4 years
    Thank you for reminding people not to copy-paste blindly
  • rohan koshti
    rohan koshti almost 4 years
    I see why you asked NOT to copy paste ... the ending } is missing... I copy pasted... :)
  • Csaba Gergely
    Csaba Gergely almost 4 years
    I can confirm this works. But use whenComplete() instead of then(), when the function got no param.
  • Erick M. Sprengel
    Erick M. Sprengel almost 4 years
    I use screenOrientation since API level 8 for Android. @BloodLoss , I think you read it on the docs, but about resizeableActivity attribute. Check the link again. ^^
  • Fillipe Silva
    Fillipe Silva almost 4 years
    If you are facing an error: "Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized." try using this fix: stackoverflow.com/questions/57689492/…
  • Golden Lion
    Golden Lion almost 4 years
    If you put SystemChrome.setPreferredOrientations in main you will get the error: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized. Inserting the code in build works because bindings have been initialized at this point.
  • RyanNa
    RyanNa about 3 years
    Reminder that for iOS info.plist, you have to set it for iPad as well under <key>UISupportedInterfaceOrientations~ipad</key>
  • mLstudent33
    mLstudent33 over 2 years
    This worked perfectly on Flutter 2.5 except the Android status bar I was hiding has returned.
  • mLstudent33
    mLstudent33 over 2 years
    I hid the Android task bar with SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom]); and adding this makes it appear again for a moment and then it goes away when I tap something to navigate. Is this by design? I have the above snippet nested in void initState() for whichever page I want to hide Android task bar and your snippet in build of my top level screen that main runs.
  • ÄR Âmmãř Żąîñh
    ÄR Âmmãř Żąîñh over 2 years
    @Boy you should change this configuration on info.plist for ipad <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> </array>
  • Johan
    Johan about 2 years
    cleanest way so far