内容简介:我此刻的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;
}
...
}
复制代码
完成
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Prometheus: Up & Running
Brian Brazil / O'Reilly Media / 2018-7-9 / USD 49.99
Get up to speed with Prometheus, the metrics-based monitoring system used by tens of thousands of organizations in production. This practical guide provides application developers, sysadmins, and DevO......一起来看看 《Prometheus: Up & Running》 这本书的介绍吧!