1. 三方库(调用原生)的使用
这里的三方库特指需要调用原生的库,目前项目里用到了react-native-share
(分享)、react-native-linear-gradient
(渐变)、react-native-splash-screen
(闪屏)、react-native-svg
(svg)。
正常我们使用react-native link
命令,原生依赖就成功地链接到你的iOS/Android项目了,但出于原生代码可能被改写的情况,需要在原生代码中确认一下引入情况:
2. lineHeight
在迁移过程发现几个页面都出现一下错误提示:
Error while updating property 'lineHeight' in shadow node of type:RCTText
查文档给出的解释:
lineHeight must be an integer, numbers with decimals are not considered as valid values.
原来安卓上lineHeight必须是整数,由于我们的项目中用了p2dp进行适配,会有把整数转成了小数的情况,解决方法就是p2dp的结果进行向上取整。
3. 字体引入
安卓上要使用自定义的字体,必须要把字体文件放在[project root]/android/app/src/main/assets/fonts/
目录下才能生效。
4. StatusBar
StatusBar是一个值得被重视的差异,它会影响到头部导航的高度样式问题,甚至是整个页面的高度问题。
4.1 StatusBar高度
- 4.1.1 Android 手机状态栏
(1)当状态栏呈现在 Andorid 手机屏幕顶部时,它会占用顶部这个空间,我们只能使用剩下的屏幕空间。也就是说如果从第 0 行开始放置组件时,组件会紧贴着状态栏的下边沿显示;
(2)要想知道实际可用的屏幕高度,可以通过手机屏幕的高度减去状态栏高度得到,安卓状态栏的高度可通过StatusBar.currentHeight
获取。 - 4.1.2 iOS 手机状态栏
(1)在 iOS 平台上,取得的屏幕高度就是实际可使用的高度;
(2)如果从第 0 行开始排列组件时,组件会紧贴着手机屏幕的最上沿显示。如果状态栏没有被隐藏,它将覆盖在第 0 行组件的上方;
(3)如果不想设置状态栏隐藏,则应当空出状态栏的显示区域。但可以为这个区域设置背景色,以使整个界面风格统一。
4.2 StatusBar样式
Default status bar style (dark for iOS, light for Android)
在Android上默认的样式是白色,而IOS是黑色,所以当我们在跨平台设置StatusBar样式时,避免使用defult
,应该直接使用light-content
、dark-content
4.3 StatusBar背景色
Android上可通过backgroundColor
设置背景色,而IOS无此属性,需要通过手动设置20dp高度的颜色作为背景色。另外项目中有个特殊需求,需要StatusBar的颜色是渐变的,这时安卓上需要让背景色透明,设置同等高度的渐变色来替代。
5. 闪屏、广告页面
因为闪屏涉及端代码的编写,自然需要重新开发。
广告页面则有两个思路:可以在端开发、也可以放在RN:
- 在端的好处在于RN的首页是"真首页",在启动应用显示闪屏的时候,为预加载首页提供了时间,让首页出现的时间大大提升;缺点就是不够灵活,如果将广告图换一个表现形式,需要重新发包。
- 在RN的好处自然就是灵活,可以频繁的变换广告形式也无需更新App,另外如果是复杂的广告形式,对于前端开发人员,开发端代码的陈本要远高于开发RN;缺点就是RN的首页变成了广告页,而不是我们想要的首页,这样启动图无法争取到首页的访问的时间,在首页呈现的时间上肯定比上面的方法慢一些。
6. 轮播组件
这个问题涉及到了第三方组件的兼容性。
之前在IOS上用的Carousel
组件在Android会有一些异常的表现。解决方案有两种:
- 修改组件源码,修复异常;
- 用一个兼容性没问题的同类组件替换
在解决过程中两种办法都尝试过,都可行。从这里也获取一个经验,之后在选择三方库的时候,尽量选择更新时间近、star数量高、仍在维护、大厂出品的。
7. 监听物理回退
由于安卓机子有一个物理回退键,如果在RN项目中不对其处理,则点击物理回退键就会关闭App,而我们的预期是希望点击后回退上一页。
首页我们要知道,点击物理回退,其实会调用端的onBackPressed
方法,所以我们需要判断如果是RN页面,应该让RN代码自行决定处理方式,当然这层逻辑其实初始化项目就做好了:
@Override
public void onBackPressed() {
//super.onBackPressed();
if(mReactInstanceManager != null){
mReactInstanceManager.onBackPressed();
}else{
super.onBackPressed();
}
}
这样我们只需要在RN项目里监听这个回退,然后处理自己想要的逻辑就行了,代码大致如下:
componentDidMount() {
if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', this._handleBack.bind(this));
}
}
componentWillUnmount() {
if (Platform.OS === 'android') {
BackHandler.removeEventListener('hardwareBackPress', this._handleBack.bind(this));
}
}
只需要在程序入口做一次监听,后续页面无需处理。
8. Modal
Android平台Modal
组件中的onRequestClose
是一个必传参数,IOS则不需要。
可以在Modal的文档上可以看到关于onRequestClose
参数的描述:
On the Android platform, this is a required function.
至于为什么只有安卓平台需要,我猜大概率和物理回退的相关处理有关系。
9. 自定义字体的高度问题
目前项目中引入了两个外部字体:思源宋和阅文定制的数字字体。
引入字体会有一定高度的上下pandding,样式处理上也有别于常规字体,需要设置lineHeight
、height
更好的定位位置。
10. Text样式之ellipsizeMode属性
Text
样式中的ellipsizeMode
属性 , 用来配合numberOfLines
显示不完全省略的位置, 可选值'head'
, 'middle'
,'tail'
,'clip'
,而其中'clip'
只能在IOS中使用,安卓平台会报错。
11. popover组件
这个问题同问题6,一样涉及到了第三方组件的兼容性。
其中比较核心的问题是安卓平台上不支持shadow阴影属性的设置,这个问题在下一条会提到。
另外这个库的开发时间比较早且已经无人维护,所以类似这样的库以后应该规避。
至于最终的解决方案,其实是加了一层蒙层来替代阴影的效果。
12. 阴影属性
在IOS上可以通过如下设置阴影:
shadowOffset: {width: 0, height: 0},
shadowColor: 'black',
shadowOpacity: 1,
shadowRadius: 5
而Android上并不支持shadow
相关的属性,只提供了一个elevation
属性,使用方法如下:
backgroundColor: 'black',
elevation: 20,
elevation顾名思义就是 “仰角”,通过为视图增加 “仰角” 方式来提供阴影,仰角越大,阴影越大。
但elevation
的设置比较局限,设置无法设置offset
。如果需要更好的效果,还是需要通过其它方式去实现,svg、渐变等,当然也有这样库提供了解决方案,像react-native-shadow、react-native-cardview都是值得参考的。
13. 触摸点击
目前关于触摸点击有以下几种方式:
- TouchableHighlight
• What it does: Darkens or lightens the background of the element when pressed.
• When to use it: On iOS for touchable elements or buttons that have a solid shape or background, and on ListView items.
- TouchableOpacity
• What it does: Lightens the opacity of the entire element when pressed.
• When to use it: On iOS for touchable elements that are standalone text or icons with no backgroundcolor.
- TouchableNativeFeedback
• What it does: Adds a ripple effect to the background when pressed.
• When to use it: On Android for almost all touchable elements.
安卓平台推荐用TouchableNativeFeedback
14. TextInput
TextInput在安卓平台默认有下划线且框内文字样式也有问题,需要做如下兼容处理:
underlineColorAndroid = "transparent" //android需要设置下划线为透明才能去掉下划线
style={{padding:0}}// 矫正样式
15. ScrollView
我们观察Android和IOS默认的下拉刷新表现形式是不一样的,这是因为安卓上的ScrollView
没有IOS的弹性bounces
,这也使得我们通过onScroll
、onScrollEndDrag
获取X轴、Y轴距离做的一些判断会有所区别。
16. react-native-scrollable-tab-view组件卡顿
这个组件在切换两个数据量稍大的Tab时,就会有明显的卡顿,开始以为是性能问题导致动画卡顿,后来debug发现是组件在切换回已经render的view,还做了一次render,导致阻塞了动画的执行,解决办法是通过shouldComponentUpdate
判断是否有必要render,当然也可以使用PureComponent来实现。