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


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


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

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


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”


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)


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

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

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

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


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.


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.