Flutter:如何按需设置和锁定屏幕方向
Posted
技术标签:
【中文标题】Flutter:如何按需设置和锁定屏幕方向【英文标题】:Flutter: How to set and lock screen orientation on-demand 【发布时间】:2018-10-23 15:01:23 【问题描述】:在我的一个颤动页面上,我需要将屏幕设置为横向模式并将其锁定,这样它就不能旋转到纵向模式,而只能在一页上。因此需要一种方法来即时启用此功能。有人知道怎么做吗?
我希望它向左或向右旋转横向,而不是进入纵向模式。
【问题讨论】:
【参考方案1】:首先导入服务包:
import 'package:flutter/services.dart';
这将使您可以访问SystemChrome
类,"Controls specific aspects of the operating system's graphical interface and how it interacts with the application."
当您加载 Widget 时,请执行以下操作:
@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();
【讨论】:
但似乎仅适用于 android github.com/flutter/flutter/issues/20124 哦,我没有意识到。很有可能,我只在安卓上测试过。 没关系,平台频道github.com/flutter/flutter/issues/13238#issuecomment-435958221可以解决,我想很快就会解决 仅指定此错误已在几个月前解决,此解决方案现在也适用于 ios 据我所知,在 dispose 方法中设置首选方向并不是一个好主意。如果您导航到另一条路线并打算返回,则不会调用 dispose 方法。【参考方案2】:我会使用一个简单的 mixin 来纵向锁定手机。以下解决方案将整个应用程序锁定为纵向 或将特定屏幕 设置为纵向,同时保持旋转。
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
【讨论】:
我已经尝试过你的 mixin 类 - 无状态版本工作得很好,但是一旦我的 statefull 类调用它的处理方法,statefull 就会抛出异常。请注意,我在课堂上打电话给super.dispose()
。以下是错误:I/flutter (29686):在最终确定小部件树时引发以下断言:I/flutter (29686):_MultiPlayerAcceptPageState.dispose 未能调用 super.dispose。 I/flutter (29686): dispose() 实现必须始终调用其超类的 dispose() 方法,以确保所有 I/flutter (29686): 小部件使用的资源都被完全释放。
有状态版本的相同异常。你解决了这个问题吗?
解决了!如果您使用 Android Studio,则可以清楚地检测到这一点。它说dispose()
被注释为@mustCallSuper
。这意味着您需要在 mixin 函数本身中添加 super.dispose()
。【参考方案3】:
void main()
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
.then((_)
runApp(new MyApp());
);
【讨论】:
虽然此代码可能会为问题提供解决方案,但最好添加有关其工作原理/方式的上下文。这可以帮助未来的用户学习并将这些知识应用到他们自己的代码中。在解释代码时,您也可能会以赞成票的形式从用户那里获得积极的反馈。【参考方案4】:首先,将整个应用方向锁定为纵向模式。
//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'
【讨论】:
无状态小部件怎么办? 您需要一个有状态的小部件来访问生命周期方法。【参考方案5】:有时由于有关方向的信息为空,它无法工作。 您可以像这样简单地使用它:
import services.dart
void main()
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]
)
.then((_)
runApp(new MyApp());
);
// 启动应用后等待设置屏幕方向 -> 然后锁定方向
【讨论】:
【参考方案6】:导入 services.dart 包并添加以下代码以将设备方向锁定为纵向模式:
import 'package:flutter/services.dart';
main()
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
runApp(MyHomePage());
【讨论】:
WidgetsFlutterBinding.ensureInitialized();
使这个解决方案对我有用。好收获!【参考方案7】:
对 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();
【讨论】:
【参考方案8】:import services.dart
和你的 void main
函数应该是这样的:
void main()
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
.then((_)
runApp(MyApp());
);
【讨论】:
【参考方案9】:在整个应用中锁定屏幕方向的简单方法
将import 'package:flutter/services.dart';
添加到main.dart
文件的开头。
在MyApp
类的Widget 构建区域中创建SystemChrome.setPreferredOrientations();
方法以禁用屏幕旋转,就在return
部分之前。
在方法的参数中使用[DeviceOrientation.<orientation-type>]
指定方向。
使用以下之一代替<orientation-type>
:
portraitUp
portraitDown
landscapeLeft
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(
),
),
);
【讨论】:
【参考方案10】:您可以为此 https://pub.dev/packages/orientation_helper 使用orientation_helper。它的主要目标是为应用中的每个屏幕设置方向。
【讨论】:
【参考方案11】:对于喜欢使用钩子的人
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();
【讨论】:
【参考方案12】:在颤振中设置首选方向。
// 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
【讨论】:
【参考方案13】:在主文件夹的AndroidManifest文件中activity标签设置android:screenOrientation = "portrait"
<activity android:windowSoftInputMode="adjustResize" android:screenOrientation = "portrait">
【讨论】:
以上是关于Flutter:如何按需设置和锁定屏幕方向的主要内容,如果未能解决你的问题,请参考以下文章