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


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


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());
    });
}

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í


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'


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)


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()),
      );

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())
        };

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());
}

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());
        }


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.


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());

-4

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.