Flutter在iOS上单页面的设备方向

8

我希望在我的Flutter应用程序中,只有一个页面以横向模式显示。其他所有屏幕都应该以纵向模式显示。

我找到了以下代码片段:

在我的main.dart文件中:

SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]).then((_) {
    runApp(new IHGApp());
  });

这将启动应用程序为竖屏模式。因此,我有一个想要在横屏模式下显示的屏幕,以下是我使用的代码:

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


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

这在Android上可行。

在iOS上似乎没有办法强制单个页面横屏模式。

https://github.com/flutter/flutter/issues/13238

在这篇文章中,我找到了解决这个问题的问题。sroddy提到了如何解决这个问题。

"我创建了一个小的平台通道来解决这个问题,在调用setPreferredOrientations之前调用此代码切换到纵向"

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];

切换到横屏的对应代码如下

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];

我该如何在我的应用程序中实现这个功能?
3个回答

3

我在我的一个应用程序中有完全相同的要求。幸运的是——整个项目都是开源的!让我们来完成它:

  1. 在iOS端的ios/Runner/AppDelegate.m上添加平台通道逻辑 - https://github.com/vintage/party_flutter/blob/27b11fc46755d8901f02c3b439b294ca9005277a/ios/Runner/AppDelegate.m#L8-L23
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;

    FlutterMethodChannel* rotationChannel = [FlutterMethodChannel
                                             methodChannelWithName:@"zgadula/orientation"
                                             binaryMessenger:controller];

    [rotationChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
        if ([@"setLandscape" isEqualToString:call.method]) {
            [[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeRight) forKey:@"orientation"];
        }
        else if ([@"setPortrait" isEqualToString:call.method]) {
            [[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
        }
        else {
            result(FlutterMethodNotImplemented);
        }
    }];

    [GeneratedPluginRegistrant registerWithRegistry:self];
    // Override point for customization after application launch.
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end
  1. 在应该采用横屏方向的widget/screen中,定义MethodChannel - https://github.com/vintage/party_flutter/blob/master/lib/ui/screens/game_play.dart#L34
static const _rotationChannel = const MethodChannel('zgadula/orientation');

3.initState应该触发横向旋转 - https://github.com/vintage/party_flutter/blob/master/lib/ui/screens/game_play.dart#L71-L78

SystemChrome.setPreferredOrientations([
  DeviceOrientation.landscapeRight,
]);
// TODO: Remove it when fixed in Flutter
// https://github.com/flutter/flutter/issues/13238
try {
  _rotationChannel.invokeMethod('setLandscape');
} catch (error) {}

try-catch是处理Android部分的(如果没有这个操作,它将正常工作,因为没有这样的通道)。

  1. 在处理完毕时 - 将其旋转回纵向模式 - https://github.com/vintage/party_flutter/blob/master/lib/ui/screens/game_play.dart#L111-L122

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

// TODO: Remove it when fixed in Flutter
// https://github.com/flutter/flutter/issues/13238
try {
  _rotationChannel.invokeMethod('setPortrait');
} catch (error) {}

if (_rotateSubscription != null) {
  _rotateSubscription.cancel();
}

可以随意更改zgadula/orientation为适合你项目的内容 :)


我尝试了使用方法通道,但当我旋转到横屏时它会崩溃。请给我一些建议。 - Shangari C

2
在我的情况下,我只使用了Flutter代码,没有使用通道。
第一步:在Xcode中更改设备可能的方向。

enter image description here

第二步。在您的应用程序的根部件中添加一个默认方向列表。通常,在 Material 应用程序小部件之前添加。
@override
  void initState() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
    super.initState();
  }

所以,现在我们的应用程序只有一种方向。
第三步。 在应该拥有其他方向的屏幕上(例如,在我的情况下,全屏视频),添加。
 @override
 void initState() {
   SystemChrome.setPreferredOrientations([
     DeviceOrientation.portraitUp,
     DeviceOrientation.landscapeRight,
     DeviceOrientation.landscapeLeft,
   ]);
   super.initState();
 }
 @override
  void dispose() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
    super.dispose();
  }

0
在我的情况下,我发现在WillPopScope小部件内恢复默认值比dispose更好,因为您将获得更平滑的弹出转换(但可能不适用于所有情况)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接