内容简介:我此刻的Flutter版本:Flutter 1.2.0 • channel dev •Framework • revision 06b979c4d5 (3 weeks ago) • 2019-01-25 14:27:35 -0500
我此刻的Flutter版本:
Flutter 1.2.0 • channel dev • github.com/flutter/flu…
Framework • revision 06b979c4d5 (3 weeks ago) • 2019-01-25 14:27:35 -0500
Engine • revision 36acd02c94
Tools • Dart 2.1.1 (build 2.1.1-dev.3.2 f4afaee422)
特定页面旋转屏幕很简单:
SystemChrome.setPreferredOrientations([ ... ]); 复制代码
数组中是您要支持的屏幕方向.
如果想在特定页面固定横屏, 您可以这样写:
@override void initState() { super.initState(); SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeRight, DeviceOrientation.landscapeRight, ]); } 复制代码
并且在 dispose
时更改回竖屏
@override void dispose() { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); super.dispose(); } 复制代码
但是!!! 不要走开 本文重点在下面
在Android设备上, 调用此方法可以强制改变屏幕方向. 但在iOS上却不是这样
对于iOS, 这个方法表示设置应用支持的屏幕方向, 只有在物理方向改变时才会改变屏幕方向
现在看起来, 这应该是一个Flutter的一个Bug. 有待官方解决
您可关注 issue #13238 追踪Flutter官方的最新更新
强制改变布局方向
既然 Flutter 提供的方法不能强制改变屏幕方向, 那么我们可以通过插件的形式, 桥接到iOS原生代码中, 通过原生方式改变屏幕方向.
设置应用支持的布局方向
通过Xcode打开Flutter项目中的iOS工程, 根据下图找到 Device Orientation
这一项 勾选需要支持的布局方向, 通过这一步, 默认你现在的应用已经会根据设备的方向转变布局了
编写插件
展开 Runner
/ Runner
文件夹 右键->New File 添加两个新的OC文件 FlutterIOSDevicePlugin.m
和 FlutterIOSDevicePlugin.h
(叫什么都没关系) 创建方式看下图:
FlutterIOSDevicePlugin.h
的内容:
#import <Flutter/Flutter.h> @interface FlutterIOSDevicePlugin : NSObject<FlutterPlugin> + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar flutterViewController:(FlutterViewController*) controller; - (instancetype)newInstance:(NSObject<FlutterPluginRegistrar>*)registrar flutterViewController:(FlutterViewController*) controller; @end 复制代码
FlutterIOSDevicePlugin.m
的内容:
#import "FlutterIOSDevicePlugin.h" @interface FlutterIOSDevicePlugin () { NSObject<FlutterPluginRegistrar> *_registrar; FlutterViewController *_controller; } @end static NSString* const CHANNEL_NAME = @"flutter_ios_device"; static NSString* const METHOD_CHANGE_ORIENTATION = @"change_screen_orientation"; static NSString* const ORIENTATION_PORTRAIT_UP = @"portraitUp"; static NSString* const ORIENTATION_PORTRAIT_DOWN = @"portraitDown"; static NSString* const ORIENTATION_LANDSCAPE_LEFT = @"landscapeLeft"; static NSString* const ORIENTATION_LANDSCAPE_RIGHT = @"landscapeRight"; @implementation FlutterIOSDevicePlugin + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:CHANNEL_NAME binaryMessenger:[registrar messenger]]; FlutterIOSDevicePlugin* instance = [[FlutterIOSDevicePlugin alloc] newInstance:registrar flutterViewController:nil]; [registrar addMethodCallDelegate:instance channel:channel]; } + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar flutterViewController:(FlutterViewController*) controller { FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:CHANNEL_NAME binaryMessenger:[registrar messenger]]; FlutterIOSDevicePlugin* instance = [[FlutterIOSDevicePlugin alloc] newInstance:registrar flutterViewController:controller]; [registrar addMethodCallDelegate:instance channel:channel]; } - (instancetype)newInstance:(NSObject<FlutterPluginRegistrar>*)registrar flutterViewController:(FlutterViewController*) controller{ _registrar = registrar; _controller = controller; return self; } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([METHOD_CHANGE_ORIENTATION isEqualToString:call.method]) { NSArray *arguments = call.arguments; NSString *orientation = arguments[0]; NSInteger iOSOrientation; if ([orientation isEqualToString:ORIENTATION_LANDSCAPE_LEFT]){ iOSOrientation = UIDeviceOrientationLandscapeLeft; }else if([orientation isEqualToString:ORIENTATION_LANDSCAPE_RIGHT]){ iOSOrientation = UIDeviceOrientationLandscapeRight; }else if ([orientation isEqualToString:ORIENTATION_PORTRAIT_DOWN]){ iOSOrientation = UIDeviceOrientationPortraitUpsideDown; }else{ iOSOrientation = UIDeviceOrientationPortrait; } [[UIDevice currentDevice] setValue:@(iOSOrientation) forKey:@"orientation"]; result(nil); } else { result(FlutterMethodNotImplemented); } } @end 复制代码
注册插件
打开 AppDelegate.m
在 didFinishLaunchingWithOptions
方法中注册插件
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; ... // flutter: Device Plugin [FlutterIOSDevicePlugin registerWithRegistrar:[self registrarForPlugin:@"FlutterIOSDevicePlugin"] flutterViewController:controller]; } 复制代码
使用插件
import 'package:flutter/services.dart'; MethodChannel _channel = const MethodChannel('flutter_ios_device'); @override void initState() { super.initState(); SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeRight, DeviceOrientation.landscapeRight, ]); if (Platform.isIOS) { changeScreenOrientation(DeviceOrientation.landscapeLeft); } } @override void dispose() { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); if (Platform.isIOS) { changeScreenOrientation(DeviceOrientation.portraitUp); } super.dispose(); } Future<void> changeScreenOrientation(DeviceOrientation orientation) { String o; switch (orientation) { case DeviceOrientation.portraitUp: o = 'portraitUp'; break; case DeviceOrientation.portraitDown: o = 'portraitDown'; break; case DeviceOrientation.landscapeLeft: o = 'landscapeLeft'; break; case DeviceOrientation.landscapeRight: o = 'landscapeRight'; break; } return _channel.invokeMethod('change_screen_orientation', [o]); } 复制代码
到此, 我们的工作基本完成. 可以强制某些特定页面改变布局方向.
还没有结束
在实践中, 我发现上面这样的做法会导致一个问题.
如果只想让特定的页面可以改变方向(横屏), 其它页面一直保持竖屏该怎么办?
"图一" 中, 我们设置了 iOS 的 Device Orientation 只要设备方向改变了, 布局就会改变.
现在, 根据图一的步骤将 Device Orientation 改为 仅 Portrait
修改 AppDelegate.h
, 加入 isLandscape
这个属性
@interface AppDelegate : FlutterAppDelegate @property (nonatomic,assign)BOOL isLandscape; @end 复制代码
在 AppDelegate.m
中加入下列方法
// 是否允许横屏 - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window{ if (self.isLandscape) { return UIInterfaceOrientationMaskAllButUpsideDown; } return UIInterfaceOrientationMaskPortrait; } 复制代码
修改 FlutterIOSDevicePlugin.m
#import "AppDelegate.h" - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { ... if ([orientation isEqualToString:ORIENTATION_LANDSCAPE_LEFT]){ iOSOrientation = UIDeviceOrientationLandscapeLeft; ((AppDelegate *)[UIApplication sharedApplication].delegate).isLandscape = YES; }else if([orientation isEqualToString:ORIENTATION_LANDSCAPE_RIGHT]){ iOSOrientation = UIDeviceOrientationLandscapeRight; ((AppDelegate *)[UIApplication sharedApplication].delegate).isLandscape = YES; }else if ([orientation isEqualToString:ORIENTATION_PORTRAIT_DOWN]){ iOSOrientation = UIDeviceOrientationPortraitUpsideDown; ((AppDelegate *)[UIApplication sharedApplication].delegate).isLandscape = NO; }else{ iOSOrientation = UIDeviceOrientationPortrait; ((AppDelegate *)[UIApplication sharedApplication].delegate).isLandscape = NO; } ... } 复制代码
完成
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python高级编程(第二版)
[波兰] Michał Jaworski、[法] Tarek Ziadé / 张亮、阿信 / 人民邮电出版社 / 2017-9-19 / 89.00元
Python作为一种高级程序设计语言,凭借其简洁、易读及可扩展性日渐成为程序设计领域备受推崇的语言之一。 本书基于Python 3.5版本进行讲解,通过13章的内容,深度揭示了Python编程的高级技巧。本书从Python语言及其社区的现状开始介绍,对Python语法、命名规则、Python包的编写、部署代码、扩展程序开发、管理代码、文档编写、测试开发、代码优化、并发编程、设计模式等重要话题......一起来看看 《Python高级编程(第二版)》 这本书的介绍吧!