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,重装一下,就可以看到启动白屏处理好了。
安卓全面屏适配及启动白屏处理
关于安卓全面屏适配及启动白屏处理,老师的视频中也有讲解,我着重让我们安卓的小伙伴做了笔记与记录,也很简单的。
网友评论