Flutter: ¿cómo evitar los cambios de orientación del dispositivo y forzar el retrato?

123

Me gustaría evitar que mi aplicación cambie su orientación y forzar el diseño para que se adhiera a "retrato".

En el main.dart, puse:

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

pero cuando uso los botones de rotación del Simulador de Android, el diseño "sigue" la orientación del nuevo dispositivo ...

¿Cómo podría solucionar esto?

Gracias

boelsi
fuente
4
Suponiendo que importó 'package:flutter/services.dart', entonces tal vez sea un error: github.com/flutter/flutter/issues/13238
Brian Kung
No estoy seguro de por qué te sucede esto. Intenté ejecutar tu código en un emulador y también en mi propio dispositivo y funciona bien.
Hemanth Raj
SystemChrome.setPreferredOrientationsdevuelve de forma asincrónica, por lo que parece que runAppdebería incluirse en un then.
Ken

Respuestas:

189

Importar package:flutter/services.dart, luego

Pon SystemChrome.setPreferredOrientationsel Widget build()método por dentro .

Ejemplo:

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

Actualizar

Es posible que esta solución no funcione para algunos dispositivos IOS como se menciona en la documentación actualizada de Flutter en octubre de 2019.

Aconsejan arreglar la orientación configurando UISupportedInterfaceOrientations en Info.plist de esta manera

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

Para obtener más información https://github.com/flutter/flutter/issues/27235#issuecomment-508995063

Masón
fuente
Trabajó. Gracias <3
Suthura Sudharaka
1
Si pones SystemChrome.setPreferredOrientations en main, obtendrás el error: Se accedió a ServicesBinding.defaultBinaryMessenger antes de que se inicializara el enlace. Insertar el código en la compilación funciona porque los enlaces se han inicializado en este punto.
León de Oro
76

@boeledi, si desea "bloquear" la orientación del dispositivo y no permitir que cambie cuando el usuario gira su teléfono, esto se configuró fácilmente como se muestra a continuación,

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

Tienes que esperar hasta setPreferredOrientationsque termine y luego iniciar la aplicación

// This will works always for lock screen Orientation.
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}
TejaDroid
fuente
A veces arroja un error durante la compilación, debe usar soluciones nativas. Agregar 'android: screenOrientation = "portrait"' a MainActivity en AndroidManifest como sugiere Abeer Iqbal funcionó para mí en Android.
Tincho825
44

iOS:

Llamar SystemChrome.setPreferredOrientations()no funciona para mí, y tuve que cambiar el Device Orientationen el proyecto Xcode de la siguiente manera:

ingrese la descripción de la imagen aquí

Androide:

Establezca el screenOrientationatributo en portraitpara la actividad principal en el archivo de la android/app/src/main/AndroidManifest.xmlsiguiente manera:

ingrese la descripción de la imagen aquí

Hejazi
fuente
Tuve el mismo problema, ¿lo ejecutaste en un iPad? Solo probé en un iPad y esto parece ser un problema: github.com/flutter/flutter/issues/27235
Boy
Android: este atributo se agregó en el nivel de API 24.
BloodLoss
Lo uso screenOrientationdesde API nivel 8 para Android. @BloodLoss, creo que lo leíste en los documentos, pero sobre resizeableActivityatributo. Vuelva a comprobar el enlace. ^^
Erick M. Sprengel
22

El método 'setPreferredOrientations' devuelve un objeto Future. Según la documentación, un futuro representa algún valor que estará disponible en algún lugar en el futuro. Es por eso que debe esperar hasta que esté disponible y luego continuar con la aplicación. Por lo tanto, se utilizará el método 'entonces', que, por definición, "registra las devoluciones de llamada que se llamarán cuando se complete el futuro". Por lo tanto, debe utilizar este código:

  void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]).then((_) {
      runApp(new App());
    });
   }

Además, se debe importar el siguiente archivo:

'paquete: flutter / services.dart'

Ara Mkrtchyan
fuente
Puedo confirmar que esto funciona. Pero use whenComplete () en lugar de then (), cuando la función no tenga un parámetro.
Csaba Gergely
20

Abra android / app / src / main / AndroidManifest.xml y agregue la siguiente línea en MainActivity:

android:screenOrientation="portrait"

Si tienes esto:

<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">

Deberías terminar con algo como esto:

<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">

Esto funciona para Android. En iOS, tendrá que cambiar esto desde la página de Xcode: https://i.stack.imgur.com/hswoe.png (como dijo Hejazi)

Abeer Iqbal
fuente
gracias, RECUERDA el orden de "retrato" después de que configChanges "orientación" importa.
MR_AMDEV
13

En primer lugar, importe esto en el archivo main.dart

import 'package:flutter/services.dart';

Entonces no copie y pegue en lugar de ver (recordar) y escribir debajo del código en el archivo main.dart

Para forzar en modo retrato :

void main() {
  SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp,DeviceOrientation.portraitDown])
      .then((_) => runApp(MyApp()),
  );

Para forzar en modo horizontal :

   void main() {
      SystemChrome.setPreferredOrientations(
          [DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight])
          .then((_) => runApp(MyApp()),
      );
Pinkesh Darji
fuente
1
Gracias por recordarle a la gente que no debe copiar y pegar a ciegas
Ryan
1
Veo por qué pediste NO copiar y pegar ... falta el final} ... copio pegado ... :)
rohan koshti
no funcionó para flutter chrome
Golden Lion
13

Coloque WidgetsFlutterBinding.ensureInitialized (); de lo contrario, obtendrá un error durante la construcción.

import 'package:flutter/services.dart';

    void main() async => {
          WidgetsFlutterBinding.ensureInitialized(),

          await SystemChrome.setPreferredOrientations(
              [DeviceOrientation.portraitUp]), // To turn off landscape mode

          runApp(MainApp())
        };
Guión
fuente
5

setPreferredOrientationdevuelve un Future<void>, por lo que es asincrónico. El enfoque más legible es definir maincomo asincrónico:

Future<void> main() async {
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  return runApp(new MyApp());
}
Rob Lyndon
fuente
3
Estoy totalmente en desacuerdo. awaites un patrón de programación ubicuo que está presente en múltiples lenguajes, y es muy claro qué expresivo. thencrea niveles de anidación. Si tiene tres o cuatro continuaciones, thencomienza a ser muy difícil de leer.
Rob Lyndon
.thense puede encadenar en lugar de anidar, como espera un FutureOr. Esto me permite utilizar un enfoque más funcional, más legible y elegante. Por ejemplo, puedo usar el cuerpo de la expresión en lugar del cuerpo entre corchetes al encadenar los "luego".
Mateus Felipe
A veces arroja un error durante la compilación, debe usar soluciones nativas. Agregar 'android: screenOrientation = "portrait"' a MainActivity en AndroidManifest como sugiere Abeer Iqbal funcionó para mí en Android.
Tincho825
Si se enfrenta a un error: "Excepción no controlada: se accedió a ServicesBinding.defaultBinaryMessenger antes de que se inicializara el enlace". intente usar esta solución: stackoverflow.com/questions/57689492/…
Fillipe Silva
1

A partir de las nuevas versiones de flutter junto con la configuración preferred Orientation, necesitamos agregar una línea adicional, es decir

 WidgetsFlutterBinding.ensureInitialized();

Entonces, el código de trabajo para esto es:

import 'package:flutter/services.dart';
    void main() {
          WidgetsFlutterBinding.ensureInitialized();
          SystemChrome.setPreferredOrientations([
            DeviceOrientation.portraitUp,
            DeviceOrientation.portraitDown
          ]);
          runApp(MyApp());
        }
B.shruti
fuente
1

A continuación se muestra el ejemplo oficial del equipo Flutter. https://github.com/flutter/samples/blob/master/veggieseasons/lib/main.dart

import 'package:flutter/services.dart' show DeviceOrientation, SystemChrome;

void main() {
    WidgetsFlutterBinding.ensureInitialized();
    SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
    ]);
    runApp(HomeScreen());
}
Lucas Martins Soares
fuente
0

Tratar

 void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await SystemChrome.setPreferredOrientations(
          [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); 
    
      runApp(MyApp());
 }

También puede cambiar la configuración de orientación de la pantalla en el manifiesto de Android y el archivo ios info.plist.

Bukunmi
fuente
0

Importar importación 'paquete: flutter / services.dart';

Luego, incluye la línea de código a continuación en su archivo main.dart, y en su método principal así:

WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitDown,
    DeviceOrientation.portraitUp,
  ]);

runApp(myApp());
Silas Ogar
fuente
-4

La mejor solución será usarlo en el método de compilación de MyApp ().

Aashar Wahla
fuente