Мерехтіння: Як встановити та заблокувати орієнтацію екрана на вимогу


83

На одній із моїх мерехтливих сторінок мені потрібно, щоб екран перейшов у альбомний режим і заблокував його, щоб він не міг повернутися в портретний режим, а лише на одній сторінці. Тож потрібен спосіб, щоб увімкнути цю функцію на льоту. Хтось знає, як це зробити?

Я хотів би, щоб він обертав альбомну ліву чи альбомну праворуч, лише не в портретному режимі.

Відповіді:


170

Спочатку імпортуйте пакет послуг:

import 'package:flutter/services.dart';

Це дасть вам доступ до SystemChromeкласу, який"Controls specific aspects of the operating system's graphical interface and how it interacts with the application."

Завантажуючи віджет, виконайте щось подібне:

@override
void initState(){
  super.initState();
  SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
  ]);
}

тоді, коли я залишаю сторінку, повертаю її до звичайного рівня так:

@override
dispose(){
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  super.dispose();
}

2
але, схоже, працює лише на android github.com/flutter/flutter/issues/20124
Луїджіно Де Тоньї

О, я не усвідомлював. Це дуже можливо, я протестував це лише на Android.
Jus10,

нічого, це може бути вирішено за допомогою платформи Channel github.com/flutter/flutter/issues/13238#issuecomment-435958221, і я думаю, що це буде виправлено найближчим часом
Luigino De Togni

20
Тільки для того, щоб визначити, що ця помилка була вирішена кілька місяців тому, і це рішення тепер працює і на iOS
Пабло Інсуа

1
З того, що я бачу, не є гарною ідеєю встановлювати бажану орієнтацію в способі розпорядження. Метод dispose не викликається, якщо ви переходите на інший маршрут і маєте намір повернутися назад.
Роуан Гонтьє,

27

Я б використав простий мікс, щоб заблокувати телефон у портреті . Наступне рішення блокує всю програму в портретному режимі або встановлює певні екрани в портретні, зберігаючи обертання в іншому випадку.

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

/// Forces portrait-only mode application-wide
/// Use this Mixin on the main app widget i.e. app.dart
/// Flutter's 'App' has to extend Stateless widget.
///
/// Call `super.build(context)` in the main build() method
/// to enable portrait only mode
mixin PortraitModeMixin on StatelessWidget {
  @override
  Widget build(BuildContext context) {
    _portraitModeOnly();
    return null;
  }
}

/// Forces portrait-only mode on a specific screen
/// Use this Mixin in the specific screen you want to
/// block to portrait only mode.
///
/// Call `super.build(context)` in the State's build() method
/// and `super.dispose();` in the State's dispose() method
mixin PortraitStatefulModeMixin<T extends StatefulWidget> on State<T> {
  @override
  Widget build(BuildContext context) {
    _portraitModeOnly();
    return null;
  }

  @override
  void dispose() {
    _enableRotation();
  }
}

/// blocks rotation; sets orientation to: portrait
void _portraitModeOnly() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
}

void _enableRotation() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]);
}

Щоб заблокувати обертання у всьому застосунку, застосуйте його PortraitModeMixinв основному Appвіджеті Чи не забудьте зателефонувати super.build(context)в Widget build(BuildContext context)методі.

/// Main App widget
class App extends StatelessWidget with PortraitModeMixin {
  const App();

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return CupertinoApp(
      title: 'Flutter Demo',
      theme: CupertinoThemeData(),
      home: Text("Block screen rotation example"),
    );
  }
}

Щоб заблокувати обертання на певному екрані, застосуйте його PortraitStatefulModeMixin<SampleScreen>до певного стану екрана. Чи не забудьте зателефонувати super.build(context)в державі build()способу і super.dispose()в dispose()методі. Якщо ваш екран є StatelessWidget - просто повторіть рішення програми (попередній приклад), тобто використовуйте PortraitModeMixin.

/// Specific screen
class SampleScreen extends StatefulWidget {
  SampleScreen() : super();

  @override
  State<StatefulWidget> createState() => _SampleScreenState();
}

class _SampleScreenState extends State<SampleScreen>
    with PortraitStatefulModeMixin<SampleScreen> {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Text("Flutter - Block screen rotation example");
  }

  @override
  void dispose() {
     super.dispose();
  }
}

Міксіни з таким синтаксисом працюють з Dart 2.1


1
Я спробував ваш клас mixin - версія без стану працює прекрасно, однак statefull видає виняток, як тільки мій statefull клас викликає свій метод disposed. Зверніть увагу, я телефоную super.dispose()в межах мого класу. Нижче наведена помилка: I / flutter (29686): Під час доопрацювання дерева віджетів було викинуто таке твердження: I / flutter (29686): _MultiPlayerAcceptPageState.dispose не вдалося викликати super.dispose. I / flutter (29686): реалізації dispose () завжди повинні викликати свій метод superclass dispose (), щоб забезпечити повне звільнення всіх I / flutter (29686): ресурсів, що використовуються віджетом.
Ангел Тодоров

Той самий виняток для версії зі станом. Ви вирішили цю проблему?
cwhisperer

5
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
    .then((_) {
      runApp(new MyApp());
    });
}

3
Хоча цей код може запропонувати вирішення питання, краще додати контекст щодо того, чому / як це працює. Це може допомогти майбутнім користувачам навчитися та застосувати ці знання до власного коду. Ви також можете отримати позитивні відгуки користувачів у вигляді голосів "за", коли пояснюється код.
borchvm

5

Іноді це не могло працювати через нульову інформацію про орієнтацію. Ви можете використовувати його просто так:

import services.dart


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

// чекаємо орієнтації екрана налаштувань після запуску програми та -> потім блокуємо орієнтацію


2

імпортувати services.dartі ваша void mainфункція повинна виглядати так:

void main(){

    WidgetsFlutterBinding.ensureInitialized();
    SystemChrome.setPreferredOrientations(
       [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
       .then((_){
           runApp(MyApp());
       }
    );
}


0

імпортуйте пакет services.dart і додайте наступний код, щоб заблокувати орієнтацію пристрою в режимі PortraitUp:

 import 'package:flutter/services.dart';

 main() {
     WidgetsFlutterBinding.ensureInitialized();
     SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
     runApp(MyHomePage());
 }

0

Важливо для iOS .

  • Увімкніть орієнтацію у файлі info.plist. наприкладвведіть тут опис зображення

Кроки

  • Встановіть орієнтацію у файлі main.dart. У моєму випадку програма "Моя програма" підтримує лише портрет, крім одного екрану, тому мені потрібно встановити портретний режим спочатку. наприклад
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp,DeviceOrientation.portraitDown,]);
  • Додайте наступний код на той екран, який потрібно повернути.
  void initState() {
    super.initState();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
  }
  @override
  dispose(){
     SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
      ]);
    super.dispose();
  }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.