轉載請標明出處: juejin.im/post/5c68da…
本文出自:Wos的主頁html
我此刻的Flutter版本:ios
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)
git
特定頁面旋轉屏幕很簡單:github
SystemChrome.setPreferredOrientations([
...
]);
複製代碼
數組中是您要支持的屏幕方向.數組
若是想在特定頁面固定橫屏, 您能夠這樣寫:bash
@override
void initState() {
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeRight,
]);
}
複製代碼
而且在dispose
時更改回豎屏app
@override
void dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
super.dispose();
}
複製代碼
可是!!! 不要走開 本文重點在下面ide
在Android設備上, 調用此方法能夠強制改變屏幕方向. 但在iOS上卻不是這樣佈局
對於iOS, 這個方法表示設置應用支持的屏幕方向, 只有在物理方向改變時纔會改變屏幕方向post
如今看起來, 這應該是一個Flutter的一個Bug. 有待官方解決
您可關注 issue #13238 追蹤Flutter官方的最新更新
發現已經有大佬將下面的方法封裝成了package (點此跳轉到orientation).
我沒有嘗試過, 你們能夠優先嚐試一下這個庫.
既然 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
方法中註冊插件
#include "FlutterIOSDevicePlugin.h"
...
- (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.landscapeLeft,
DeviceOrientation.landscapeRight,
]).then((_) {
if (Platform.isIOS) {
iOSDevicePlugin.changeScreenOrientation(DeviceOrientation.landscapeLeft);
}
});
}
@override
void dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]).then((_) {
if (Platform.isIOS) {
iOSDevicePlugin.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;
}
...
}
複製代碼
完成
SystemChrome.setPreferredOrientations does not force the device to the given orientations until the device is physically rotated #13238
iOS關於橫屏的有關問題
ios啓動頁強制豎屏(進入App後容許橫屏與豎屏)
我對iOS知之甚少, 以上解決方案全憑網上的資料彙總, 暫時沒有能力提供 flutter plugin 供你們快速接入. 若有高手寫了相關庫請告知我, 我會將它放到這篇文章中. 感謝