美文网首页
RN:全面屏适配及启动白屏处理

RN:全面屏适配及启动白屏处理

作者: 意一ineyee | 来源:发表于2019-08-28 11:10 被阅读0次

iOS全面屏适配


我们先把适配前和适配后的效果图放在这里。

适配前 适配后

通过上面的效果图,我们看出react-navigation已经自动帮我们做好了底部TabBar的全面屏适配,那我们只需要做一下顶部导航栏的全面屏适配就好了。

我们第一眼想到的、最简单的全面屏适配方法就是:判断一下机型,然后给导航栏和TabBar不同的高度,就可以完成适配了。因为全面屏手机的状态栏高度是44,TabBar高度是83,而非全面屏手机的状态栏高度是20,TabBar高度是49,这样给出不同的高度,就可以避免全面屏情况下布局的偏差,以及因此而导致的用户操作超出安全域。

上面的方法的确可以解决导航栏和TabBar全面屏适配问题,但是如果遇见上图“自定义语言”界面底部那种情况呢?在布局上应该给底部留出一些空间的,否则用户操作超出了安全域,根本点不到想点的选项。所以说我们只通过上述方法做导航栏和TabBar全面屏适配是不够的,我们得另想办法:判断一下机型,如果是全面屏,就在屏幕的顶部塞一个24(44 - 20)高度的View,底部塞一个34(83 - 49)高度的View。同时为了避免在每个界面都写这段重复的代码,我们对这段代码进行封装,封装出一个容器组件ProjectSafeAreaView,我们只要在把它作为每个界面的根组件就可以完成全面屏的适配了。

-----------ProjectSafeAreaView.js-----------

import React, {Component} from 'react';
import {Platform, StyleSheet, View, SafeAreaView, DeviceInfo} from 'react-native';
import {PropTypes} from 'prop-types';

export default class ProjectSafeAreaView extends React.Component {
    /*-----------生命周期方法-----------*/

    static propTypes = {
        // 是否显示顶部视图
        showTopView: PropTypes.bool,
        // 是否显示底部视图
        showBottomView: PropTypes.bool,

        // 顶部视图颜色
        topViewColor: PropTypes.string,
        // 底部视图颜色
        bottomViewColor: PropTypes.string,
    };

    static defaultProps = {
        showTopView: true,
        showBottomView: false,

        topViewColor: 'transparent',
        bottomViewColor: '#f8f8f8',
    };

    render() {
        return (
            this._genProjectSafeAreaView()
        );
    }


    /*-----------私有方法-----------*/

    _genProjectSafeAreaView() {
        // children为外界使用时,套在ProjectSafeAreaView内部的子组件们,这是系统提供的属性,不要随便改名字
        const {children, showTopView, showBottomView, topViewColor, bottomViewColor} = this.props;
        return (
            <View style={[styles.container, this.props.style]}>
                {this._genTopView(showTopView, topViewColor)}
                {children}
                {this._genBottomView(showBottomView, bottomViewColor)}
            </View>
        );
    }

    _genSafeAreaView() {
        // children为外界使用时,套在ProjectSafeAreaView内部的子组件们,这是系统提供的属性,不要随便改名字
        const {children} = this.props;
        return(
            <SafeAreaView style={[styles.container, this.props.style]} {...this.props}>
                {children}
            </SafeAreaView>
        );
    }

    _genTopView(showTopView, topViewColor) {
        return(
            DeviceInfo.isIPhoneX_deprecated && showTopView ? <View style={[styles.topView, {backgroundColor: topViewColor}]}/> : null
        );
    }

    _genBottomView(showBottomView, bottomViewColor) {
        return(
            DeviceInfo.isIPhoneX_deprecated && showBottomView ? <View style={[styles.bottomView, {backgroundColor: bottomViewColor}]}/> : null
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },

    topView: {
        // iPhoneX的状态栏比普通机型的高出了顶部的24
        height: 24,
    },
    bottomView: {
        // iPhoneX的TabBar比普通机型的高出了底部的34
        height: 34,
    },
});

接下来,我们分别在“我的”和“自定义语言”界面使用该组件,把原来的根组件View,替换成ProjectSafeAreaView就可以了。

-----------MinePage.js-----------

// 适配前
render() {
    return (
        <View style={styles.container}>
            // 子组件...
        </View >
    );
}

// 适配后
render() {
    return (
        <ProjectSafeAreaView
            style={styles.container}
            topViewColor={ProjectSingleton.sharedSingleton().themeColor}
        >
            // 子组件...
        </ProjectSafeAreaView>
    );
}
-----------CustomKeysAndLanguagesPage.js-----------

// 适配前
render() {
    return (
        <View style={styles.container}>
            // 子组件...
        </View >
    );
}

// 适配后
render() {
    return (
        <ProjectSafeAreaView
            style={styles.container}
            topViewColor={ProjectSingleton.sharedSingleton().themeColor}
            showBottomView={true}
        >
            // 子组件...
        </ProjectSafeAreaView>
    );
}

当然,App中不是所有的界面都能用这个完成全面屏的适配,比如我们使用了一些三方的组件,根本没法用这个包的时候,就得额外的处理那个界面的适配工作。

iOS启动白屏处理


我们先把处理前和处理后的效果图放在这里。

处理前 处理后

RN App在启动时会出现白屏现象,时间大概是1~3s(根据手机或模拟器的性能不同而不同)。

原因是RN App在启动时会将JS包读取到内存中,并完成渲染。那么在JS包还没有完全读取完毕并渲染出来前,界面就显示的是白屏。

具体的分析详见此文,我们考虑把白屏的这段时间隐藏起来,让JS包的读取过程在背后悄悄咪咪地执行,而是让App多展示会儿启动页,具体的实现详见此文。我们直接使用该组件吧。

RN项目中:

yarn add react-native-splash-screen

react-native link react-native-splash-screen

iOS项目中:

-----------AppDelegate.m-----------

#import "RNSplashScreen.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  
  // 一些代码
  
  // 显示SplashScreen,这一句一定要在最后
  [RNSplashScreen show];
  
  return YES;
}

RN项目中:

-----------WelcomePage.js-----------

import SplashScreen from 'react-native-splash-screen';

export default class WelcomePage extends Component {
    render() {
        // 可以做做广告了什么的
        return null;
    }

    componentDidMount() {
        this.timer = setTimeout(() => {
            // 关闭SplashScreen
            SplashScreen.hide();

            NavigationUtil.navigate('StackNavigator');
        }, 1000);
    }

    componentWillUnmount() {
        if (this.timer) {
            clearTimeout(this.timer);
        }
    }
}

iOS项目中:

像原生项目那样配置好启动图LaunchImage,卸载掉App,重装一下,就可以看到启动白屏处理好了。

安卓全面屏适配及启动白屏处理


关于安卓全面屏适配及启动白屏处理,老师的视频中也有讲解,我着重让我们安卓的小伙伴做了笔记与记录,也很简单的。

相关文章

网友评论

      本文标题:RN:全面屏适配及启动白屏处理

      本文链接:https://www.haomeiwen.com/subject/fkrpectx.html