Reprint please indicate the source: juejin.cn/post/684490… This post is from: Wos homepage
My current Flutter version:
Flutter 1.2.0 • channel dev • github.com/flutter/flu… Framework • Revision 06B979C4D5 (3 weeks ago) • Engine • Tools • Dart 3.2 f4afaee422 2.1.1 (build 2.1.1 – dev.)
Rotating the screen for a particular page is simple:
SystemChrome.setPreferredOrientations([ ... ] );Copy the code
In the array is the screen orientation you want to support.
If you want to fix landscape on a particular page, you can write:
@override
void initState() {
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeRight,
]);
}
Copy the code
And change back to portrait screen when dispose
@override
void dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
super.dispose();
}
Copy the code
But!!!!!! Stay tuned for the rest of this article
On Android devices, this method can be called to force a change in screen orientation. That’s not the case on iOS
For iOS, this method means setting the screen orientation supported by the app, and only changing the screen orientation when the physical orientation changes
Now it seems that this is a Bug in Flutter. It needs to be resolved officially
You can follow issue #13238 for the latest updates to Flutter officials
Force layout orientation changes
The 2019-03-15 update:
Find that the following methods have been packaged as package (click here to go to orientation).
I haven’t tried it, so you can try this library first.
Since the methods provided by Flutter cannot force screen orientation changes, we can change screen orientation natively by using a plugin that Bridges into the native iOS code.
Set the layout direction supported by the application
Open the iOS project in the Flutter project with Xcode. Check the Device Orientation TAB in the image below to select the layout Orientation you want to support. By doing this, your current application will change its layout according to the Device Orientation by default
Writing a plug-in
Add two OC files flutteriosdeviceplugin.m and flutteriosdeviceplugin.h.
Contents of 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
Copy the code
Contents of 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); } } @endCopy the code
To register the plugin
Open the AppDelegate. M registered in didFinishLaunchingWithOptions method plug-ins
#include "FlutterIOSDevicePlugin.h". - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; . // flutter: Device Plugin [FlutterIOSDevicePlugin registerWithRegistrar:[self registrarForPlugin:@"FlutterIOSDevicePlugin"] flutterViewController:controller];
}
Copy the code
The use of plug-in
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 voiddispose() {
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]);
}
Copy the code
At this point, our work is basically complete. You can force specific pages to change layout orientation.
It’s not over yet
In practice, I’ve found that doing this leads to a problem.
What if you only want certain pages to be reoriented (landscape), but the rest of the pages remain portrait?
In “Figure 1”, we set the iOS Device Orientation to change the layout whenever the Device Orientation changes.
Now, follow the steps in Figure 1 to change Device Orientation to Portrait only
Modify appdelegate. h to add isLandscape
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,assign)BOOL isLandscape;
@end
Copy the code
Add the following methods to appdelegate.m
/ / whether to allow landscape - (UIInterfaceOrientationMask) application: (UIApplication *) application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window{if (self.isLandscape) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
Copy the code
Modify 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; }... }Copy the code
complete
Reference:
SystemChrome.setPreferredOrientations does not force the device to the given orientations until the device is physically The iOS startup screen mandatory portrait, all of which were allowed after entering the App
I know little about iOS. The above solutions are all summarized on the Internet. For the time being, I am not able to provide quick access to the Flutter Plugin. If there is a master to write the relevant library please let me know, I will put it in this article. Thank you