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