Flutter:如何按需设置和锁定屏幕方向

Flutter: How to set and lock screen orientation on-demand

在我的一个 flutter 页面上,我需要将屏幕设置为横向模式并将其锁定,这样它就不能旋转到纵向模式,但只能在一页上。所以需要一种方法来即时启用此功能。有人知道怎么做吗?

我希望它向左横向或向右旋转,只是不要进入纵向模式。

首先导入服务包:

import 'package:flutter/services.dart';

这将使您能够访问 SystemChrome class,其中 "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();
}

我会使用一个简单的mixin锁定phone纵向。以下解决方案将整个应用程序锁定为纵向将特定屏幕设置为纵向,同时保持其他屏幕旋转。

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,
  ]);
}

在整个应用程序中阻止旋转 在主要 App 小部件中实施 PortraitModeMixin。记得在Widget build(BuildContext context)方法中调用super.build(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>。记得在State的build()方法中调用super.build(context),在dispose()方法中调用super.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 的具有这种语法的 Mixins

有时由于有关方向的信息为空,因此无法正常工作。 您可以像这样简单地使用它:

import services.dart


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

// 启动应用后等待设置屏幕方向 -> 然后锁定方向

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

import services.dart 你的 void main 函数应该是这样的:

void main(){

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

您可以为此 https://pub.dev/packages/orientation_helper 使用 orientation_helper。它的主要目标是为应用程序中的每个屏幕设置方向。

导入 services.dart 包并添加以下代码以将设备方向锁定为 portraitUp 模式:

 import 'package:flutter/services.dart';

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

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

首先,将整个应用程序方向锁定为纵向模式。

//Do this in main.dart
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
  .then((_) {
runApp(MyApp());
});

其次,转到要更改方向的特定屏幕。

@override
void initState() {
super.initState();

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

}

@override
void dispose() {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
_interstitialAd.dispose();
super.dispose();
}

要使用 SystemChrome,您必须添加 'package:flutter/services.dart'

在整个应用程序中锁定屏幕方向的简单方法

  • import 'package:flutter/services.dart'; 添加到 main.dart 文件的开头。

  • 创建 SystemChrome.setPreferredOrientations(); 方法以在 MyApp class 的 return 部分之前的 Widget 构建区域中禁用屏幕旋转。

  • 在方法的参数中使用 [DeviceOrientation.<orientation-type>] 指定方向。

使用以下选项之一代替 <orientation-type>

  1. portraitUp
  2. portraitDown
  3. landscapeLeft
  4. landscapeRight

示例代码:

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(
        appBar: AppBar(
        title: Text("Screen Orientation"),
        ),
        body: Container(
        ),
      ),
    );
  }
}

对于那些喜欢使用钩子的人

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

useOrientation(List<DeviceOrientation> orientations) {
  useEffect(
    () {
      SystemChrome.setPreferredOrientations(orientations);
      return () {
        SystemChrome.setPreferredOrientations([
          DeviceOrientation.portraitUp,
          DeviceOrientation.portraitDown,
          DeviceOrientation.landscapeLeft,
          DeviceOrientation.landscapeRight,
        ]);
      };
    },
  );
}

像这样使用它:

class MyWidget extends HookWidget {
  void build(BuildContext context) {

    useOrientation([DeviceOrientation.portraitUp]);

    return Container();
  }
}

设置flutter中的首选方向。

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

// Lock the orientation to Portrait Only
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((value) => runApp(MyApp()));

您还可以在 setPreferredOrientations 列表中添加首选方向,例如 [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]

以下是您可以设置的方向:

/// If the device shows its boot logo in portrait, then the boot logo is shown
  /// in [portraitUp]. Otherwise, the device shows its boot logo in landscape
  /// and this orientation is obtained by rotating the device 90 degrees
  /// clockwise from its boot orientation.
  portraitUp,

  /// The orientation that is 90 degrees clockwise from [portraitUp].
  ///
  /// If the device shows its boot logo in landscape, then the boot logo is
  /// shown in [landscapeLeft].
  landscapeLeft,

  /// The orientation that is 180 degrees from [portraitUp].
  portraitDown,

  /// The orientation that is 90 degrees counterclockwise from [portraitUp].
  landscapeRight,

参考:https://greymag.medium.com/flutter-orientation-lock-portrait-only-c98910ebd769

在 activity 标签下主文件夹中的 AndroidManifest 文件中设置 android:screenOrientation = "portrait"

<activity android:windowSoftInputMode="adjustResize" android:screenOrientation = "portrait">

在GetX中,你需要像这个例子一样使用GetBuilder:

final Controller ctrl = Get.find();

GetBuilder<Controller>(
  initState: (_) => ctrl.setLandscape(),
  dispose: (_) => ctrl.setPortrait(),
  builder: (code) => Container(
      padding: const EdgeInsets.zero,
      alignment: Alignment.Center,
      child: const SizedBox(),
   ),
),

In Controller file: 
class Controller extends GetxController {
  RxBool isLandscape = false.obs;

  Future<void> setLandscape() async {
    if (isLandscape.isTrue) {
      await SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]);
      update();
    }
  }
  
  Future<void> setPortrait() async {
    if (isLandscape.isFalse) {
      await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
      update();
    }
  }
}
我希望这个解决方案能够回答使用 GetX 作为主要状态管理的开发人员。祝你好运,兄弟!上帝保佑你们。