最近需要做个平板的项目,然后需要直接横屏,有2种实现方式。

1, 随着屏幕旋转,布局自动调整。做横竖屏适配

2,强制屏幕横屏,不随着屏幕去调整

第一种方式这里就不做说明了。代码做适配就可以。 下面说一下第二种实现方式

Flutter 自带方式

flutter 为我们提供了方法来控制系统的横竖屏显示

 SystemChrome.setPreferredOrientations([
   DeviceOrientation.landscapeLeft,
   DeviceOrientation.landscapeRight,
   DeviceOrientation.portraitUp,
   DeviceOrientation.portraitDown
  ]).then((_) {
  });

包含的方向类型。 !!!!但是但是但是这个方法只适用于android在iOS上没有效果,上网查资料有大神封装的 flutter插件orientation ,flutter插件auto_orientation 在iOS上都起不到效果,所以打算自己写一个原生文件与flutter进行通讯,实现屏幕旋转。也是笔者在查询资料之后做的一个整合和解释说明

iOS端实现屏幕旋转

创建iOS原生文件

创建iOS原生文件来实现交互,首先要创建个原生文件。命名为FlutterIOSDevicePlugin。 创建文件

创建一个命名为FlutterIOSDevicePlugin.h 和命名为FlutterIOSDevicePlugin.m文件,说明一下: FlutterIOSDevicePlugin.h文件选择图片里面的header File模块创建即可。

创建之后,一起看一下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

以上是全部的代码,其中尝试了用通知的方式去做屏幕旋转,后来发现其实没有那么麻烦,直接采用的是

[[UIDevice currentDevice] setValue:@(iOSOrientation) forKey:@"orientation"];

方式做的。其中遇到的问题:

问题1:iphone手机上可以正常旋转,ipad上不行

这个问题主要原因是info。plist文件里面的iphone和ipad不一致,且勾选Requires full screen 即可

回到正轨哈

注册原生插件文件

iOS 工程种有个GeneratedPluginRegistrant.m文件,直接注册就可以了。 如果你项目引入了其他第三方插件,也是统一在这个地方注册的

#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文件中的设置

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方法是控制监听的事件的方法,目前没什么用。 主要代码是这一段,这个是在发出屏幕旋转的时候回调的方法,这里面设置的是全部的方向都可以。

  override func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return orientationMask;
  }

问题2:程序不走该方法

具体原因是因为info.plist文件问题。参考上面设置就没问题

flutter 原生代码使用

这个地方是针对于iOS平台去做的区别。

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: 启动程序自动旋转

SystemChrome.setPreferredOrientations需要设置全部内容。不然会默认旋转。有点小坑,

以上基本上可以实现屏幕旋转的问题,如果有小伙伴还是不行,可以试一下用iOS原生通知的方式去完成。这个我做的是平板的项目,暂时没有问题,更多相关Flutter 控制屏幕旋转内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Flutter 控制屏幕旋转的实现的更多相关文章

  1. Flutter中文教程-Cookbook

    Flutter中文网的Cookbook中包含了在编写Flutter应用程序时常见问题及示例。设计基础使用主题共享颜色和字体样式Images显示来自网上的图片用占位符淡入图片使用缓存图Lists创建一个基本list创建一个水平list使用长列表创建不同类型子项的List创建一个gridList处理手势处理点击添加Material触摸水波效果实现滑动关闭导航导航到新页面并返回给新页面传值从新页面返回数据给上一个页面网络从网上获取数据进行认证请求使用WebSockets

  2. android-studio – 未配置Dart SDK

    Initializinggradle…

  3. 安卓 – 从一个扑动的应用程序拨打电话

    或者有更好的选择从我的应用程序拨打电话?

  4. android – 如何在Flutter中添加Webview?

    我知道可以将WebView添加为整页,但找不到任何示例代码.我假设你可以使用PageView作为它的基础,但不知道如何调用本机androidWebView并将其添加到PageView.谁能指出我正确的方向?

  5. android – 如何将消息从Flutter传递给Native?

    如果需要与特定的API/硬件组件进行交互,您如何将Flutter的信息传递回Android/Native代码?是否有任何事件频道可以通过其他方式发送信息或类似于回调?

  6. android – 如何在Flutter App中处理onPause / onResume?

    我是否过于复杂的事情?即使我的用例似乎不需要它,我仍然想知道:如何自己处理onPause/onResume事件?

  7. android – 如何使用Flutter构建Augment Reality应用程序?

    我对Android开发有一些基础知识.最近听说过Flutter并且非常有兴趣研究它.我想知道是否有可能使用颤振构建增强现实应用程序以及要实现此目的的方法?请帮忙.解决方法截至目前,颤振不支持3D.Flutter现在专注于2D,团队长期计划为颤振提供优化的3Dapi.你读了常见问题here.

  8. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  9. Flutter StreamBuilder实现局部刷新实例详解

    这篇文章主要为大家介绍了Flutter StreamBuilder实现局部刷新实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. Flutter 首页必用组件NestedScrollView的示例详解

    今天介绍的组件是NestedScrollView,大部分的App首页都会用到这个组件。对Flutter 首页必用组件NestedScrollView的相关知识感兴趣的一起看看吧

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部