Flutter: como evitar mudanças na orientação do dispositivo e forçar o retrato?

124

Gostaria de evitar que meu aplicativo altere sua orientação e forçar o layout a ficar em "retrato".

No main.dart, coloco:

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

mas quando uso os botões de rotação do Android Simulator, o layout "segue" a nova orientação do dispositivo ...

Como eu poderia resolver isso?

obrigado

Boeledi
fonte
4
Supondo que você importou 'package:flutter/services.dart', talvez seja um bug: github.com/flutter/flutter/issues/13238
Brian Kung
Não sei por que isso acontece com você. Tentei rodar seu código em um emulador e também no meu próprio dispositivo e funcionou bem.
Hemanth Raj,
SystemChrome.setPreferredOrientationsretorna de forma assíncrona, então parece que runAppdeve estar entre um then.
Ken

Respostas:

191

Importar package:flutter/services.dartentão

Coloque SystemChrome.setPreferredOrientationsdentro do Widget build()método.

Exemplo:

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

Atualizar

Esta solução pode não funcionar para alguns dispositivos IOS, conforme mencionado na documentação atualizada do flutter em outubro de 2019.

Eles aconselham corrigir a orientação definindo UISupportedInterfaceOrientations em Info.plist como este

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

Para mais informações https://github.com/flutter/flutter/issues/27235#issuecomment-508995063

Pedreiro
fonte
Trabalhou. Obrigado <3
Suthura Sudharaka
1
Se você colocar SystemChrome.setPreferredOrientations em main, obterá o erro: ServicesBinding.defaultBinaryMessenger foi acessado antes da ligação ser inicializada. Inserir o código na construção funciona porque as ligações foram inicializadas neste ponto.
Golden Lion
77

@boeledi, se você deseja “bloquear” a orientação do dispositivo e não permitir que ela mude conforme o usuário gira o telefone, isso foi facilmente definido como abaixo,

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

Você tem que esperar até setPreferredOrientationsterminar e, em seguida, iniciar o aplicativo

// This will works always for lock screen Orientation.
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}
TejaDroid
fonte
Às vezes, gera um erro durante a compilação, você deve usar soluções nativas. Adicionar 'android: screenOrientation = "portrait"' a MainActivity no AndroidManifest, como sugere Abeer Iqbal, funcionou para mim no Android.
Tincho825
44

iOS:

Chamar SystemChrome.setPreferredOrientations()não funciona para mim e tive que alterar o Device Orientationno projeto Xcode da seguinte forma:

insira a descrição da imagem aqui

Android:

Defina o screenOrientationatributo para portraitpara a atividade principal no arquivo da android/app/src/main/AndroidManifest.xmlseguinte forma:

insira a descrição da imagem aqui

Hejazi
fonte
Eu tive o mesmo problema, você executou em um iPad? Testei apenas em um iPad e isso parece ser um problema: github.com/flutter/flutter/issues/27235
Garoto,
android: este atributo foi adicionado na API nível 24.
BloodLoss
Eu uso screenOrientationdesde a API nível 8 para Android. @BloodLoss, acho que você leu na documentação, mas sobre o resizeableActivityatributo. Verifique o link novamente. ^^
Erick M. Sprengel
22

O método 'setPreferredOrientations' retorna um objeto Future. Por documentação, um Futuro representa algum valor que estará disponível em algum lugar no futuro. É por isso que você deve esperar até que esteja disponível e então prosseguir com o aplicativo. Portanto, deve ser utilizado o método 'then', que, por definição, "registra callbacks a serem chamados quando o Future for concluído". Portanto, você deve usar este código:

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

Além disso, o seguinte arquivo deve ser importado:

'pacote: flutter / services.dart'

Ara Mkrtchyan
fonte
Posso confirmar que isso funciona. Mas use whenComplete () em vez de then (), quando a função não tiver nenhum parâmetro.
Csaba Gergely
20

Abra android / app / src / main / AndroidManifest.xml e adicione a seguinte linha em MainActivity:

android:screenOrientation="portrait"

Se você tem este:

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

Você deve acabar com algo assim:

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

Isso funciona para Android. No iOS, você terá que alterar isso na página do Xcode: https://i.stack.imgur.com/hswoe.png (como Hejazi disse)

Abeer Iqbal
fonte
obrigado, LEMBRE-SE que a ordem de "retrato" depois que a "orientação" do configChanges é importante.
MR_AMDEV
13

Em primeiro lugar, importe isso no arquivo main.dart

import 'package:flutter/services.dart';

Então não copie e cole, em vez de ver (lembrar) e escrever o código abaixo no arquivo main.dart

Para forçar no modo retrato :

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

Para forçar no modo paisagem :

   void main() {
      SystemChrome.setPreferredOrientations(
          [DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight])
          .then((_) => runApp(MyApp()),
      );
Pinkesh Darji
fonte
1
Obrigado por lembrar as pessoas de não copiar e colar às cegas
Ryan
1
Eu vejo porque você pediu para NÃO copiar, colar ... o final} está faltando ... Eu
copiei
não funcionou para cromo vibratório
Golden Lion
13

Coloque o WidgetsFlutterBinding.ensureInitialized () do contrário, você obterá um erro durante a construção.

import 'package:flutter/services.dart';

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

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

          runApp(MainApp())
        };
Traço
fonte
5

setPreferredOrientationretorna a Future<void>, por isso é assíncrono. A abordagem mais legível é definir maincomo assíncrono:

Future<void> main() async {
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  return runApp(new MyApp());
}
Rob Lyndon
fonte
3
Eu discordo fortemente. awaité um padrão de programação onipresente que está presente em várias linguagens, e é muito claro o que é expressivo. thencria níveis de aninhamento. Se você tem três ou quatro continuações, thencomeça a ficar realmente muito difícil de ler.
Rob Lyndon
.thenpode ser encadeado em vez de aninhado, pois espera a FutureOr. Isso me permite usar uma abordagem mais funcional, que é mais legível e elegante. Por exemplo, posso usar o corpo da expressão em vez do corpo entre colchetes, encadeando o "então".
Mateus Felipe
Às vezes, gera um erro durante a compilação, você deve usar soluções nativas. Adicionar 'android: screenOrientation = "portrait"' a MainActivity no AndroidManifest, como sugere Abeer Iqbal, funcionou para mim no Android.
Tincho825
Se você estiver enfrentando um erro: "Unhandled Exception: ServicesBinding.defaultBinaryMessenger foi acessado antes da ligação ser inicializada." tente usar esta correção: stackoverflow.com/questions/57689492/…
Fillipe Silva
1

A partir de novas versões de flutter, juntamente com a configuração preferred Orientation, precisamos adicionar uma linha extra, ou seja,

 WidgetsFlutterBinding.ensureInitialized();

Portanto, o código de trabalho para isso é -

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

Abaixo está o exemplo oficial da equipe de 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
fonte
0

Experimentar

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

Você também pode alterar as configurações de orientação da tela no manifesto do Android e no arquivo ios info.plist.

Bukunmi
fonte
0

Import import 'package: flutter / services.dart';

Em seguida, você inclui a linha de código abaixo em seu arquivo main.dart e em seu método principal da seguinte forma:

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

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

A melhor solução será usá-lo no método de construção de MyApp ().

Aashar Wahla
fonte