当前位置:   article > 正文

ReactNative进阶(三十六):iOS 横屏适配_react native横屏应用

react native横屏应用

一、前言

应用RN技术栈实现APP上线后,业务部门领导会上反馈未实现ipad横屏全屏展示,用户体验较差。由此,一场pad横屏全屏展示的APP调优工作由此开展。

实操环境:

  • Xcode: 14.2
  • react-native-cli: 2.0.1
  • react-native: 0.60.3
  • iOS: 16.1.2 (iPhone X)

二、实现思路

时间紧任务重,技术实现上,考虑到存量功能代码改造工作量,RN层面对于横屏改造工作量较大,故RN层面整体实现横屏展示时间上不允许,RN侧改造方案放弃。

由于业务方只关注APP某一功能模块,故将改造范围缩减,当业务方点击APP功能模块入口时,允许APP解除屏幕方向锁定,让屏幕方向根据设备的物理方向自动调整。当应用退出当前关注功能模块时,APP屏幕方向锁定,不允许屏幕方向根据设备的物理方向自动调整。

APP默认仅支持竖屏。

2.1 Android

操作如下:
app/src/main/AndroidManifest.xml配置文件中添加android:screenOrientation="portrait"

值得注意的是:需要在activity中添加并且是在属性为android:name=".MainActivity"下添加以上配置,如图:

在这里插入图片描述

2.2 iOS端

为实现iPad适配,首先需要将Targeted Device Families更改为iPhone, iPad

在这里插入图片描述

在Xcode项目中把相对应的勾去掉即可。

在这里插入图片描述

基于项目为react-native技术栈实现,不涉及原生代码,可借助react-native第三方组件:react-native-orientation实现。

安装步骤:

npm i --save react-native-orientation
react-native link react-native-orientation (自动link不成功,建议手动link)
  • 1
  • 2

进入功能模块时,

import Orientation from 'react-native-orientation';

onPress={() => {
  // 解除屏幕方向锁定,让屏幕方向根据设备的物理方向自动调整
  console.log('----------解除屏幕方向锁定,让屏幕方向根据设备的物理方向自动调整---------');
  Orientation.unlockAllOrientations();
  ....
}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

退出功能模块时,

import Orientation from 'react-native-orientation';

initData = () => {
  // 锁定屏幕竖屏锁定
  console.log('----------锁定屏幕竖屏锁定---------');
  Orientation.lockToPortrait();
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

按照以上实现思路实施后,发现android系统下的pad表现较好,能够按照预期设想自动实现APP横竖屏切换,且内容适配。

但是,iOS系统下的iPhone、iPad表现不尽如人意,虽然可以实现屏幕横竖屏自动切换,但是当APP处于横屏状态下时,页面展示效果存在未完全铺展开的适配问题。

在这里插入图片描述

显而易见,iOS系统中当旋转物理设备至横屏时,仍然沿用的设备竖屏状态下的宽高进行页面绘制。关键问题就出在这里。

且发现在RN页面及webview中均存在横屏状态下沿用竖屏状态宽高问题。

按照网上给出的解决方案:

对于iOS,在ios/Info.plist文件中包括以下行就可以了:

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
</array>

<key>UISupportedInterfaceOrientations~ipad</key>
<array>
    <string>UIInterfaceOrientationLandscapeRight</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

经实践发现问题依旧存在。且存在整个APP应用横竖屏切换时,样式错乱(竖屏状态应用横屏样式,遮挡)问题。

经过控制台日志分析发现如下兼容性提示信息:

> [Orientation] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:)
  • 1

iOS 16 中,通过设置 UIDevice.orientation 来强制旋转屏幕的方向已不再被支持。
根据错误提示,需要使用 UIWindowScene.requestGeometryUpdate(_:) 方法来实现。

转为 iOS 15.2.1测试机后,发现以上兼容性提示信息在控制台不再展示。
但是竖屏转横屏后,依旧存在样式错乱(竖屏状态应用横屏样式,遮挡)问题。

经过项目实践,发现组件react-native-orientation对于iOS系统横竖屏转换支持并不友好,也有可能自己遗漏了xcode配置。

三、延伸阅读

3.1 iOS 原生实现横竖屏切换

3.1.1 iOS16 之前实现横竖屏切换

AppDelegate.h 文件中添加一个变量来记录是否需要进行横竖屏切换。

@property (nonatomic, assign, getter=isLaunchScreen) BOOL launchScreen;    /**< 是否是横屏 */
  • 1

AppDelegate.m 文件中重写 launchScreensetter 方法:

- (void)setLaunchScreen:(BOOL)launchScreen {

    _launchScreen = launchScreen;
    [self application:[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:nil];
}
  • 1
  • 2
  • 3
  • 4
  • 5

并且实现 UIApplicationDelegateapplication:supportedInterfaceOrientationsForWindow: 方法

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {

    if (self.isLaunchScreen) {
        // 只支持横屏,并且 Home 按键在右边
        return UIInterfaceOrientationMaskLandscapeRight;
    }

    // 只支持竖屏
    return UIInterfaceOrientationMaskPortrait;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

接下来在需要切换横竖屏的 View 中增加以下方法,就能在 iOS16 之前实现该功能。

/// 切换设备方向
/// - Parameter isLaunchScreen: 是否是全屏
- (void)p_switchOrientationWithLaunchScreen:(BOOL)isLaunchScreen {
    AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    if (isLaunchScreen) {
        // 全屏操作
        appdelegate.launchScreen = YES;
    } else {
        // 退出全屏操作
        appdelegate.launchScreen = NO;
    }
    // 设置设备的方向
    [self p_swichToNewOrientation:isLaunchScreen ? UIInterfaceOrientationLandscapeRight : UIInterfaceOrientationPortrait];
}

/// iOS16 之前进行横竖屏切换方式
/// - Parameter interfaceOrientation: 需要切换的方向
- (void)p_swichToNewOrientation:(UIInterfaceOrientation)interfaceOrientation {
    NSNumber *orientationTarget = [NSNumber numberWithInteger:interfaceOrientation];
    [[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

经过以上代码,就能实现在 iOS16 之前的设备上进行横竖屏切换,下面开始适配 iOS16 的横竖屏切换。

3.1.2 iOS16 之后实现横竖屏切换

跟 iOS16 之前方式一样,需要设置 launchScreen 标志变量,重写 launchScreensetter 方法,实现 UIApplicationDelegateapplication:supportedInterfaceOrientationsForWindow: 方法。

在Xcode 14下,需要实现横竖屏切换的 View p_switchOrientationWithLaunchScreen: 方法中增加 iOS16 适配。

/// 切换设备方向
/// - Parameter isLaunchScreen: 是否是全屏
- (void)p_switchOrientationWithLaunchScreen:(BOOL)isLaunchScreen {

    AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    if (isLaunchScreen) {
        // 全屏操作
        appdelegate.launchScreen = YES;
    } else {
        // 退出全屏操作
        appdelegate.launchScreen = NO;
    }

    if (@available(iOS 16.0, *)) {
        // setNeedsUpdateOfSupportedInterfaceOrientations 方法是 UIViewController 的方法,所以这个操作最好是放在控制器中去操作
        [self setNeedsUpdateOfSupportedInterfaceOrientations];
        NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
        UIWindowScene *scene = [array firstObject];
        // 屏幕方向
        UIInterfaceOrientationMask orientation = isLaunchScreen ? UIInterfaceOrientationMaskLandscapeRight : UIInterfaceOrientationMaskPortrait;
        UIWindowSceneGeometryPreferencesIOS *geometryPreferencesIOS = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientation];
        // 开始切换
        [scene requestGeometryUpdateWithPreferences:geometryPreferencesIOS errorHandler:^(NSError * _Nonnull error) {
            NSLog(@"强制%@错误:%@", isLaunchScreen ? @"横屏" : @"竖屏", error);
        }];
    } else {
        [self p_swichToNewOrientation:isLaunchScreen ? UIInterfaceOrientationLandscapeRight : UIInterfaceOrientationPortrait];
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

3.2 react-native-orientation 可用函数

react-native-orientation 组件可用函数如下:

  • lockToPortrait()
  • lockToLandscape()
  • lockToLandscapeLeft()
  • lockToLandscapeRight()
  • unlockAllOrientations()
  • getOrientation(function(err, orientation) 返回的结果有 LANDSCAPEPORTRAITUNKNOWNPORTRAITUPSIDEDOWN
  • getSpecificOrientation(function(err, specificOrientation) 返回的结果有 LANDSCAPE-LEFTLANDSCAPE-RIGHTPORTRAITUNKNOWNPORTRAITUPSIDEDOWN

官方文档中,还有一些事件的介绍,详细可以到官方文档上了解学习。

3.3 从模拟器中删除以前的应用程序

  1. 删除...../Library/Developer/Xcode/DerivedData中的所有文件;
  2. 然后从Xcode(Product->Clean Build Folder)中清除构建文件夹。

然后运行应用程序,

3.4 Xcode Crash报错提示Message from debugger: Terminated due to signal 9

原因:

  1. 内存使用过高

  2. CPU使用过高

当内存或者CPU使用过高时,系统会杀死进程。需要启动任务管理器,杀掉无用进程。

3.5 react-native-full-screen (仅支持Android)

react-native-full-screen 是一个用于 React Native 库,它提供了一种简单的方式来实现Android全屏显示。通过使用这个库,可以轻松地将React Native应用程序设置为全屏模式,以提供更好的用户体验。

该库提供了一些方法和组件,可以实现全屏显示。其中包括:

  1. FullScreen.enableFullScreen(): 这个方法可以将应用程序设置为全屏模式。调用这个方法后,应用程序将占据整个屏幕,并隐藏系统的状态栏和导航栏。

  2. FullScreen.disableFullScreen(): 这个方法可以将应用程序从全屏模式切换回正常模式。调用这个方法后,应用程序将恢复到原来的显示状态,显示系统的状态栏和导航栏。

  3. FullScreen.FullScreenView: 这个组件可以用作容器,将其包裹在需要全屏显示的内容周围。当这个组件被渲染时,它会自动将其子组件设置为全屏模式。

使用react-native-full-screen库,可以轻松地实现全屏显示,并根据需要在全屏和正常模式之间进行切换。

应用时,首先安装依赖包:

npm install react-native-full-screen --save
  • 1

然后,链接库。

react-native link react-native-full-screen
  • 1

使用时,首先导入依赖,

import FullScreen from 'react-native-full-screen';
  • 1

在需要横屏的代码点,做如下逻辑处理:

FullScreen.onFullScreen();
  • 1

若自动link不成功,建议手动link,可参照react-native-orientation

安装时,注意RN 0.60 及以上不需要执行 link 操作。

(RN 0.60 and and above)

npm install @hortau/react-native-orientation-locker
  • 1

(RN 0.59 and and below)

npm install @hortau/react-native-orientation-locker

react-native link @hortau/react-native-orientation-locker
  • 1
  • 2
  • 3

3.6 react-native-orientation-locker

react-native-orientation-locker 使用方式与 react-native-orientation 相同。

四、拓展阅读

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/564176
推荐阅读
相关标签
  

闽ICP备14008679号