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.