Flutter 控制屏幕旋轉(zhuǎn)的實現(xiàn)
最近需要做個平板的項目,然后需要直接橫屏,有2種實現(xiàn)方式。
1, 隨著屏幕旋轉(zhuǎn),布局自動調(diào)整。做橫豎屏適配
2,強制屏幕橫屏,不隨著屏幕去調(diào)整
第一種方式這里就不做說明了。代碼做適配就可以。 下面說一下第二種實現(xiàn)方式
Flutter 自帶方式
flutter 為我們提供了方法來控制系統(tǒng)的橫豎屏顯示
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]).then((_) {
});
包含的方向類型。 ?。。?!但是但是但是這個方法只適用于android在iOS上沒有效果,上網(wǎng)查資料有大神封裝的 flutter插件orientation ,flutter插件auto_orientation 在iOS上都起不到效果,所以打算自己寫一個原生文件與flutter進行通訊,實現(xiàn)屏幕旋轉(zhuǎn)。也是筆者在查詢資料之后做的一個整合和解釋說明
iOS端實現(xiàn)屏幕旋轉(zhuǎn)
創(chuàng)建iOS原生文件
創(chuàng)建iOS原生文件來實現(xiàn)交互,首先要創(chuàng)建個原生文件。命名為FlutterIOSDevicePlugin。 創(chuàng)建文件

創(chuàng)建一個命名為FlutterIOSDevicePlugin.h 和命名為FlutterIOSDevicePlugin.m文件,說明一下: FlutterIOSDevicePlugin.h文件選擇圖片里面的header File模塊創(chuàng)建即可。
創(chuàng)建之后,一起看一下FlutterIOSDevicePlugin.h里面的代碼
#ifndef FlutterIOSDevicePlugin_h #define 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 #endif /* FlutterIOSDevicePlugin_h */
這個不需要過多說明了看一下FlutterIOSDevicePlugin.m的代碼
#import <Foundation/Foundation.h>
#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];
NSNumber *index = [NSNumber numberWithInt: [call.arguments[0] intValue]];
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"];
// [[NSNotificationCenter defaultCenter] postNotificationName:@"FlutterIOSDevicePlugin" object:nil userInfo:@{@"orientationMask": index}];
// [UIViewController attemptRotationToDeviceOrientation];
result(nil);
} else {
result(FlutterMethodNotImplemented);
}
}
@end
以上是全部的代碼,其中嘗試了用通知的方式去做屏幕旋轉(zhuǎn),后來發(fā)現(xiàn)其實沒有那么麻煩,直接采用的是
[[UIDevice currentDevice] setValue:@(iOSOrientation) forKey:@"orientation"];
方式做的。其中遇到的問題:
問題1:iphone手機上可以正常旋轉(zhuǎn),ipad上不行
這個問題主要原因是info。plist文件里面的iphone和ipad不一致,且勾選Requires full screen 即可

回到正軌哈
注冊原生插件文件
iOS 工程種有個GeneratedPluginRegistrant.m文件,直接注冊就可以了。 如果你項目引入了其他第三方插件,也是統(tǒng)一在這個地方注冊的
#import "GeneratedPluginRegistrant.h"
#if __has_include(<auto_orientation/AutoOrientationPlugin.h>)
#import <auto_orientation/AutoOrientationPlugin.h>
#else
@import auto_orientation;
#endif
#if __has_include(<orientation/OrientationPlugin.h>)
#import <orientation/OrientationPlugin.h>
#else
@import orientation;
#endif
#import "FlutterIOSDevicePlugin.h"
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[AutoOrientationPlugin registerWithRegistrar:[registry registrarForPlugin:@"AutoOrientationPlugin"]];
[OrientationPlugin registerWithRegistrar:[registry registrarForPlugin:@"OrientationPlugin"]];
// [registry registrarForPlugin:@"FlutterIOSDevicePlugin"];
[FlutterIOSDevicePlugin registerWithRegistrar: [registry registrarForPlugin:@"FlutterIOSDevicePlugin"]];
}
@end
代碼中的這個片段是自己寫的插件注冊的方法,其他的AutoOrientationPlugin,OrientationPlugin是引用第三方插件自動生成的代碼。
[FlutterIOSDevicePlugin registerWithRegistrar: [registry registrarForPlugin:@"FlutterIOSDevicePlugin"]];
AppDelegate文件中的設(shè)置
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var orientationMask: UIInterfaceOrientationMask = .all;
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(changeLandscape(center:)), name:NSNotification.Name(rawValue: "FlutterIOSDevicePlugin"), object: nil)
GeneratedPluginRegistrant.register(with: self);
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return orientationMask;
}
@objc func changeLandscape(center: Notification){
let index: NSNumber = (center.userInfo?["orientationMask"] ?? 5) as! NSNumber
var mask : UIInterfaceOrientationMask = .all
switch index {
case 0:
mask = .portrait
break
case 1:
mask = .landscapeLeft
break
case 2:
mask = .landscapeRight
break
case 3:
mask = .portraitUpsideDown
break
case 4:
mask = .landscape
break
case 5:
mask = .all
break
case 6:
mask = .allButUpsideDown
break
default:
mask = .all
break
}
orientationMask = mask;
_ = application(UIApplication.shared, supportedInterfaceOrientationsFor: UIApplication.shared.keyWindow)
}
}
其中changeLandscape方法是控制監(jiān)聽的事件的方法,目前沒什么用。 主要代碼是這一段,這個是在發(fā)出屏幕旋轉(zhuǎn)的時候回調(diào)的方法,這里面設(shè)置的是全部的方向都可以。
override func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return orientationMask;
}
問題2:程序不走該方法
具體原因是因為info.plist文件問題。參考上面設(shè)置就沒問題
flutter 原生代碼使用
這個地方是針對于iOS平臺去做的區(qū)別。
MethodChannel _channel = const MethodChannel('flutter_ios_device');
@override
void initState() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]).then((_) {
if (Platform.isIOS) {
this.changeScreenOrientation(DeviceOrientation.landscapeLeft);
}
});
super.initState();
}
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]);
}
代碼不用過多說明了, 有不了解的可以留言
問題3: 啟動程序自動旋轉(zhuǎn)
SystemChrome.setPreferredOrientations需要設(shè)置全部內(nèi)容。不然會默認旋轉(zhuǎn)。有點小坑,
以上基本上可以實現(xiàn)屏幕旋轉(zhuǎn)的問題,如果有小伙伴還是不行,可以試一下用iOS原生通知的方式去完成。這個我做的是平板的項目,暫時沒有問題,更多相關(guān)Flutter 控制屏幕旋轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Android提交數(shù)據(jù)到服務(wù)器的兩種方式四種方法
本篇文章主要介紹了Android提交數(shù)據(jù)到服務(wù)器的兩種方式四種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-11-11
Android編輯框EditText與焦點變更監(jiān)視器及文本變化監(jiān)視器實現(xiàn)流程詳解
這篇文章主要介紹了Android編輯框EditText與焦點變更監(jiān)視器及文本變化監(jiān)視器實現(xiàn)流程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09
Android_UI 仿QQ側(cè)滑菜單效果的實現(xiàn)
相信大家對QQ側(cè)滑菜單的效果已經(jīng)不陌生了吧,側(cè)滑進入個人頭像一側(cè),進行對頭像的更改,我的收藏,QQ錢包,我的文件等一系列的操作,下面小編給大家分享Android_UI 仿QQ側(cè)滑菜單效果的實現(xiàn),一起看看吧2017-04-04
Android實現(xiàn)從本地圖庫/相機拍照后裁剪圖片并設(shè)置頭像
玩qq或者是微信的盆友都知道,這些聊天工具里都要設(shè)置頭像,一般情況下大家的解決辦法是從本地圖庫選擇圖片或是從相機拍照,然后根據(jù)自己的喜愛截取圖片,接下來通過本文給大家介紹Android實現(xiàn)從本地圖庫/相機拍照后裁剪圖片并設(shè)置頭像,需要的朋友參考下2016-02-02
android計算pad或手機的分辨率/像素/密度/屏幕尺寸/DPI值的方法
本文將介紹手機布局/界面設(shè)計/分辨率/密度相關(guān),接下來介紹android計算pad或手機的分辨率像素等等的方法,感興趣的朋友可以了解下,希望本文可以幫助你2013-01-01
Android使用MediaCodec將攝像頭采集的視頻編碼為h264
這篇文章主要為大家詳細介紹了Android使用MediaCodec將攝像頭采集的視頻編碼為h264,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-10-10
Android編程實現(xiàn)EditText字數(shù)監(jiān)聽并顯示的方法
這篇文章主要介紹了Android編程實現(xiàn)EditText字數(shù)監(jiān)聽并顯示的方法,涉及Android EditText文本框事件監(jiān)聽與響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-02-02

