Flutter: jak zapobiec zmianom orientacji urządzenia i wymusić portret?

124

Chciałbym uniemożliwić mojej aplikacji zmianę orientacji i zmusić układ do trzymania się „portretu”.

W main.dart umieściłem:

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

ale kiedy używam przycisków obracania symulatora Androida, układ „podąża” za nową orientacją urządzenia ...

Jak mogłem to rozwiązać?

Dzięki

boeledi
źródło
4
Zakładając, że zaimportowałeś 'package:flutter/services.dart', może to błąd: github.com/flutter/flutter/issues/13238
Brian Kung
Nie jestem pewien, dlaczego tak się dzieje. Próbowałem uruchomić twój kod na emulatorze, a także na moim własnym urządzeniu i działa dobrze.
Hemanth Raj
SystemChrome.setPreferredOrientationszwraca asynchronicznie, więc wydaje się, że runApppowinien być ujęty w then.
Ken

Odpowiedzi:

194

Import package:flutter/services.dart, a następnie

Umieść metodę SystemChrome.setPreferredOrientationswewnątrz Widget build().

Przykład:

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

Aktualizacja

To rozwiązanie może nie działać w przypadku niektórych urządzeń z systemem IOS, jak wspomniano w zaktualizowanej dokumentacji fluttera z października 2019 r.

Zalecają ustalenie orientacji, ustawiając UISupportedInterfaceOrientations w Info.plist w ten sposób

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

Aby uzyskać więcej informacji, https://github.com/flutter/flutter/issues/27235#issuecomment-508995063

Mason
źródło
Pracował. Dziękuję <3
Suthura Sudharaka
1
Jeśli umieścisz SystemChrome.setPreferredOrientations w main, otrzymasz błąd: uzyskano dostęp do ServicesBinding.defaultBinaryMessenger przed zainicjowaniem wiązania. Wstawianie kodu do kompilacji działa, ponieważ w tym momencie zainicjowano powiązania.
Golden Lion
77

@boeledi, Jeśli chcesz „zablokować” orientację urządzenia i nie pozwolić na jej zmianę, gdy użytkownik obraca telefon, można to łatwo ustawić jak poniżej,

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

Musisz poczekać, aż setPreferredOrientationssię skończy, a następnie uruchomić aplikację

// This will works always for lock screen Orientation.
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}
TejaDroid
źródło
1
Czasami generuje błąd podczas kompilacji, powinieneś użyć rozwiązań natywnych. Dodanie „android: screenOrientation =" portrait "” do MainActivity na AndroidManifest, jak sugeruje Abeer Iqbal's, działało dla mnie na Androidzie.
Tincho825
45

iOS:

Wywołanie SystemChrome.setPreferredOrientations()nie działa dla mnie i musiałem zmienić Device Orientationw projekcie Xcode w następujący sposób:

wprowadź opis obrazu tutaj

Android:

Ustaw screenOrientationatrybut na portraitdla głównego działania w pliku android/app/src/main/AndroidManifest.xmlw następujący sposób:

wprowadź opis obrazu tutaj

Hejazi
źródło
Miałem ten sam problem, czy uruchomiłeś go na iPadzie? Testowałem tylko na iPadzie i wydaje się, że to problem: github.com/flutter/flutter/issues/27235
Boy
android: ten atrybut został dodany na poziomie API 24.
BloodLoss
Używam screenOrientationod poziomu API 8 dla Androida. @BloodLoss, myślę, że przeczytałeś to w dokumentacji, ale o resizeableActivityatrybucie. Sprawdź łącze ponownie. ^^
Erick M. Sprengel
22

Metoda „setPreferredOrientations” zwraca obiekt Future. Według dokumentacji przyszłość reprezentuje pewną wartość, która będzie dostępna gdzieś w przyszłości. Dlatego należy poczekać, aż będzie dostępny, a następnie przejść do aplikacji. W związku z tym powinna zostać użyta metoda „then”, która zgodnie z definicją „rejestruje wywołania zwrotne, które zostaną wywołane, gdy Future się zakończy”. Dlatego powinieneś użyć tego kodu:

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

Należy również zaimportować następujący plik:

„package: flutter / services.dart”

Ara Mkrtchyan
źródło
Mogę potwierdzić, że to działa. Ale użyj whenComplete () zamiast then (), gdy funkcja nie ma parametru.
Csaba Gergely
20

Otwórz android / app / src / main / AndroidManifest.xml i dodaj następujący wiersz w MainActivity:

android:screenOrientation="portrait"

Jeśli masz to:

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

Powinieneś otrzymać coś takiego:

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

Działa to na Androida. W iOS będziesz musiał to zmienić na stronie Xcode: https://i.stack.imgur.com/hswoe.png (jak powiedział Hejazi)

Abeer Iqbal
źródło
dzięki, PAMIĘTAJ, że kolejność „portret” po „orientacji” configChanges ma znaczenie.
MR_AMDEV
13

Przede wszystkim zaimportuj to do pliku main.dart

import 'package:flutter/services.dart';

Następnie nie kopiuj wklejania, a zobacz (pamiętaj) i napisz poniższy kod w pliku main.dart

Aby wymusić tryb portretowy :

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

Aby wymusić w trybie poziomym :

   void main() {
      SystemChrome.setPreferredOrientations(
          [DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight])
          .then((_) => runApp(MyApp()),
      );
Pinkesh Darji
źródło
1
Dziękuję za przypomnienie ludziom, aby nie kopiowali i wklejali na ślepo
Ryan
1
Rozumiem, dlaczego prosiłeś o NIE kopiowanie wklejania ... brakuje końcówki} ...
kopiuję
nie działał na flutter chrome
Golden Lion
13

Umieść WidgetsFlutterBinding.ensureInitialized (), w przeciwnym razie wystąpi błąd podczas budowania.

import 'package:flutter/services.dart';

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

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

          runApp(MainApp())
        };
Dziarskość
źródło
5

setPreferredOrientationzwraca a Future<void>, więc jest asynchroniczna. Najbardziej czytelnym podejściem jest zdefiniowanie mainjako asynchroniczne:

Future<void> main() async {
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  return runApp(new MyApp());
}
Rob Lyndon
źródło
3
Zdecydowanie się nie zgadzam. awaitto wszechobecny wzorzec programowania, który jest obecny w wielu językach i jest bardzo jasne, co jest ekspresyjne. thentworzy poziomy zagnieżdżenia. Jeśli masz trzy lub cztery kontynuacje, thenczytanie zaczyna być bardzo trudne.
Rob Lyndon
.thenmożna łączyć zamiast zagnieżdżać, ponieważ oczekuje, że plik FutureOr. Dzięki temu mogę zastosować bardziej funkcjonalne podejście, które jest bardziej czytelne i eleganckie. Na przykład mogę użyć treści wyrażenia zamiast treści w nawiasach, łącząc „wtedy”.
Mateus Felipe
Czasami generuje błąd podczas kompilacji, powinieneś użyć rozwiązań natywnych. Dodanie „android: screenOrientation =" portrait "” do MainActivity na AndroidManifest, jak sugeruje Abeer Iqbal's, działało dla mnie na Androidzie.
Tincho825
Jeśli napotkasz błąd: „Nieobsłużony wyjątek: uzyskano dostęp do ServicesBinding.defaultBinaryMessenger przed zainicjowaniem powiązania”. spróbuj użyć tej poprawki: stackoverflow.com/questions/57689492/ ...
Fillipe Silva
1

Od nowych wersji fluttera wraz z ustawieniem preferred Orientationmusimy dodać jedną dodatkową linię tj

 WidgetsFlutterBinding.ensureInitialized();

Tak więc działający kod to -

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

Poniżej znajduje się oficjalny przykład zespołu 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
źródło
0

Próbować

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

Możesz także zmienić ustawienia orientacji ekranu w manifeście systemu Android i pliku info.plist systemu iOS.

Bukunmi
źródło
0

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

Następnie umieść poniższy wiersz kodu w pliku main.dart oraz w swojej głównej metodzie, tak jak poniżej:

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

runApp(myApp());
Silas Ogar
źródło
-4

Najlepszym rozwiązaniem będzie użycie go w metodzie kompilacji MyApp ().

Aashar Wahla
źródło