Flutter: как предотвратить изменение ориентации устройства и принудительный портрет?

132

Я бы хотел, чтобы мое приложение не меняло ориентацию и заставляло макет придерживаться «портретной» ориентации.

В main.dart я положил:

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

но когда я использую кнопки поворота Android Simulator, макет "следует" за новой ориентацией устройства ...

Как я мог это решить?

Спасибо

Boeledi
источник
4
Если вы импортировали 'package:flutter/services.dart', то, возможно, это ошибка: github.com/flutter/flutter/issues/13238
Брайан Кунг,
Не знаю, почему это происходит с вами. Я пробовал запустить ваш код на эмуляторе, а также на моем собственном устройстве, и он отлично работает.
Hemanth Raj
SystemChrome.setPreferredOrientationsвозвращается асинхронно, поэтому кажется, что его runAppследует заключить в then.
Кен

Ответы:

202

Импортировать package:flutter/services.dart, затем

Поместите метод SystemChrome.setPreferredOrientationsвнутрь Widget build().

Пример:

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

Обновить

Это решение может не работать для некоторых устройств IOS, как упоминалось в обновленной документации по флаттеру от октября 2019 года.

Они советуют зафиксировать ориентацию, установив UISupportedInterfaceOrientations в Info.plist следующим образом

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

Для получения дополнительной информации https://github.com/flutter/flutter/issues/27235#issuecomment-508995063

Мейсон
источник
Работал. Спасибо <3
Сутура Судхарака
1
Если вы поместите SystemChrome.setPreferredOrientations в основной, вы получите сообщение об ошибке: доступ к ServicesBinding.defaultBinaryMessenger был осуществлен до инициализации привязки. Вставка кода в сборку работает, потому что привязки были инициализированы на этом этапе.
Golden Lion
Спасибо. Это помогает мне и экономит мое время.
Ронак
77

@boeledi, если вы хотите «заблокировать» ориентацию устройства и не позволять ей изменяться, когда пользователь поворачивает свой телефон, это можно легко установить, как показано ниже,

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

Вам нужно подождать, пока не setPreferredOrientationsбудет сделано, а затем запустить приложение

// This will works always for lock screen Orientation.
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}
TejaDroid
источник
1
Иногда при компиляции возникает ошибка, вам следует использовать собственные решения. Добавление 'android: screenOrientation = "portrait"' к MainActivity на AndroidManifest, как предлагает Абир Икбал, сработало для меня на Android.
Tincho825,
46

iOS:

Звонки SystemChrome.setPreferredOrientations()у меня не работают, и мне пришлось изменить Device Orientationв проекте Xcode следующее:

введите описание изображения здесь

Android:

Установите screenOrientationатрибут portraitдля основного действия в файле android/app/src/main/AndroidManifest.xmlследующим образом:

введите описание изображения здесь

Хиджази
источник
У меня была такая же проблема, вы запускали на iPad? Я тестировал только на iPad, и, похоже, это проблема: github.com/flutter/flutter/issues/27235
Мальчик,
android: этот атрибут был добавлен на уровне API 24.
BloodLoss
Использую screenOrientationс уровня API 8 для Android. @BloodLoss, я думаю, вы читали это в документации, но об resizeableActivityатрибуте. Проверьте ссылку еще раз. ^^
Эрик М. Шпренгель
22

Метод setPreferredOrientations возвращает объект Future. Согласно документации, будущее представляет собой некоторую ценность, которая будет доступна где-то в будущем. Вот почему вы должны дождаться, пока он станет доступен, а затем продолжить работу с приложением. Следовательно, должен использоваться метод 'then', который, по определению, «регистрирует обратные вызовы, которые будут вызываться по завершении Future». Следовательно, вы должны использовать этот код:

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

Также необходимо импортировать следующий файл:

'пакет: flutter / services.dart'

Ара Мкртчян
источник
Я могу подтвердить, что это работает. Но используйте whenComplete () вместо then (), когда функция не имеет параметра.
Чаба Гергей,
22

Откройте android / app / src / main / AndroidManifest.xml и добавьте следующую строку в MainActivity:

android:screenOrientation="portrait"

Если у вас есть это:

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

У вас должно получиться что-то вроде этого:

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

Это работает на Android. В iOS вам нужно будет изменить это на странице Xcode: https://i.stack.imgur.com/hswoe.png (как сказал Хиджази)

Абер Икбал
источник
спасибо, ПОМНИТЕ порядок "портрета" после "ориентации" configChanges имеет значение.
MR_AMDEV
13

Прежде всего, импортируйте это в файл main.dart

import 'package:flutter/services.dart';

Тогда не копируйте вставку, а посмотрите (запомните) и напишите ниже код в файле main.dart

Чтобы заставить в портретном режиме:

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

Чтобы заставить работать в ландшафтном режиме:

   void main() {
      SystemChrome.setPreferredOrientations(
          [DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight])
          .then((_) => runApp(MyApp()),
      );
Пинкеш Дарджи
источник
1
Спасибо, что напомнили людям не копировать слепо
Райан
1
Я понимаю, почему вы просили НЕ копировать вставку ... отсутствует окончание} ... Копирую вставлено ... :)
rohan koshti
13

Поместите WidgetsFlutterBinding.ensureInitialized (), иначе вы получите ошибку при сборке.

import 'package:flutter/services.dart';

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

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

          runApp(MainApp())
        };
Тире
источник
5

setPreferredOrientationвозвращает Future<void>, поэтому он является асинхронным. Самый читаемый подход - определить mainкак асинхронный:

Future<void> main() async {
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  return runApp(new MyApp());
}
Роб Линдон
источник
3
Я категорически не согласен. await- это повсеместный шаблон программирования, который присутствует на нескольких языках, и очень ясно, что выразительно. thenсоздает уровни вложенности. Если у вас есть три или четыре продолжения, thenстановится действительно очень трудно читать.
Роб Линдон
.thenможно связать вместо вложенности, как ожидается FutureOr. Это позволяет мне использовать более функциональный подход, более читаемый и элегантный. Например, я могу использовать тело выражения вместо тела в квадратных скобках, связав «thens».
Матеуш Фелипе
Иногда при компиляции возникает ошибка, вам следует использовать собственные решения. Добавление 'android: screenOrientation = "portrait"' к MainActivity на AndroidManifest, как предлагает Абир Икбал, сработало для меня на Android.
Tincho825,
Если вы столкнулись с ошибкой: «Необработанное исключение: доступ к ServicesBinding.defaultBinaryMessenger был осуществлен до инициализации привязки». попробуйте использовать это исправление: stackoverflow.com/questions/57689492/…
Филипе Сильва
3

Просто добавьте следующую строку кода в файл main.dart.

SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
]);

и не забудьте импортировать файл services.dart. Пример приведен ниже!

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

void main() {
    runApp(MyApp());
}


class MyApp extends StatelessWidget {
     @override
     Widget build(BuildContext context) {

      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
      ]);

      return MaterialApp(
        home: Scaffold(
          body: Center(child: Text("A Flutter Example!")),
     ),
   );
  }
}
Прабхас Кумра
источник
2

Ниже приведен официальный пример команды 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());
}
Лукас Мартинс Соареш
источник
1

Что касается новых версий флаттера, вместе с настройкой preferred Orientationнам нужно добавить одну дополнительную строку, т.е.

 WidgetsFlutterBinding.ensureInitialized();

Итак, рабочий код для этого -

import 'package:flutter/services.dart';
    void main() {
          WidgetsFlutterBinding.ensureInitialized();
          SystemChrome.setPreferredOrientations([
            DeviceOrientation.portraitUp,
            DeviceOrientation.portraitDown
          ]);
          runApp(MyApp());
        }
Б.шрути
источник
1

Импортировать import 'package: flutter / services.dart';

Затем вы включаете строку кода ниже в свой файл main.dart и в свой основной метод следующим образом:

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

runApp(myApp());
Сайлас Огар
источник
0

Пытаться

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

Вы также можете изменить настройки ориентации экрана в манифесте Android и файле ios info.plist.

Букунми
источник
-4

Лучшим решением будет использовать его в методе сборки MyApp ().

Аашар Вахла
источник