lk1ngaa7 / react-native-platform-difference

React Native 双平台差异及解决方法

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

#React Native 双平台差异及解决方法(0.20)

标签及属性差异

--

1. TextInput

  • iOS下的textAlign取值 auto left right center justify
  • android下的textAlign取值为 start center end
    安卓平台有黑色边框和选中黄框,可通过设置underlineColorAndroid='rgba(0,0,0,0)'去掉
    安卓平台无清除按钮,可以使用 react-native-textinput 来兼容双平台

2. Image

  • iOS下resizeMode可以写在行间属性,也可以写在style,后者覆盖前者
  • android下resizeMode只可以写在行间,写在style无效
    //android 
    <Image resizeMode={'stretch'}></Image>
    //ios, style中的cover会覆盖掉stretch
    <Image resizeMode={'stretch'} style={{'resizeMode': 'cover'}}></Image>

3. Text

  • iOS下最主要的paddinglineHeight的 style 属性都正常支持
  • android下paddinglineHeight无效,包括单独支持 android 的textAlignVertical enum('auto', 'top', 'bottom', 'center') 也不支持,解决办法就是 padding 改用 margin,或 padding 改用父节点 paddinglineHeight 改用 marginTop 负值
    //双平台

    let isAndroid = Platform.OS === 'android';

    let styleTextLine1 = {
    	fontSize: 12,
    	marginBottom: 20,
	};
	let styleTextLine2 = {
		fontSize: 50,
		height: 50,
		lineHeight: 50, // ios
		marginTop: isAndroid ? -15 : 0,
	};

    <View style={{height: 100, justifyContent: 'center', alignItems: 'center'}}>
    	<Text style={styleTextLine1}>第一行,要求与第二行有间隔 20,字体大小 12</Text>
    	<Text style={styleTextLine2}>第二行,要求字体大小 50,字体上下居中,高度 50</Text>
    </View>

4. style position: 'absolute'

  • iOS下正常
  • android下,position: 'absolute' 超过父节点高宽部分,会隐藏掉。解决办法:当需要用position: 'absolute'的时候,恰巧要求:子节点定位超出父节点高或宽,放弃使用,改用别的布局,或者将子节点放到于父节点同级,再定位。

5. style borderRadius

  • iOS下正常
  • Android下,不支持类似borderTopLeftRadius这种写法

API差异

--

1. api NativeMethodsMixin static measure(callback: MeasureOnSuccessCallback)

  • iOS下正常
  • android下,回调函数获取不到视图的尺寸 xywidthheigthpageXpageY 等值。可以考虑用 onLayout 属性来代替,需要注意的是,需要计算 layout 的视图,载入之后,防止内部不必要的重绘引起的尺寸变化,基本上保证 state 改变后,视图的尺寸即可预见。

常见问题:

--

1. 返回事件的处理

  • iOS如果使用NavigatorIOS,并且设置了navigationBarHidden={true}(隐藏NavigationBar),将会导致右滑返回手势失效,解决方法:使用Navigator代替,但需要自己设置切场动画。
  • android物理返回键,需要在每个Navigator的源头使用BackAndroid做监听,如果this.navigator.state.routeStack.length === 1,则可以认为当前处于根view,可以退出app。否则将navigator往回退1即可。
    //android
    import React, {Navigator, BackAndroid} from 'react-native';
    //拓展类似于NavigatorIOS的popN
    Navigator.prototype.popN = function(n) {
        let routeStack = this.state.routeStack;
        let index = routeStack.length - n - 1;
        if (routeStack[index]) {
            this.popToRoute(routeStack[index]);
        }
    };
    class MyApp extends React.Component {
        ...
        componentDidMount(){
            BackAndroid.addEventListener('hardwareBackPress', () => {
                //不在根view, 往回退1,阻止退出
                if(this._navigator.state.routeStack.length > 1){
                    this._navigator.popN(1);
                    return true;
                }
                //在根view,退出(或再次点击退出)
                else{
                    return false;
                }
            });
        }
        render(){
            <Navigator
                ref={(navigator) => {
                    if(navigator !== this._navigator){
                        this._navigator = navigator;
                    }
                }}
            />
        }
    }

2. 有关屏幕的高度Dimensions.get('window').height

  • 两个平台都是整个屏幕的高度(包含statusBar, 安卓端不包含虚拟按键)

  • iOS平台的布局是从statusBar的顶端开始

  • android平台的布局是从statusBar的底端开始(设置translucent: true后也从statusBar顶端开始)

  • 如果设置view的高度是Dimensions.get('window').height,然后设置position: 'absolute', top: 0,会发现android平台view的底端被遮住了一小部分,这一小部分正好就是android平台statusBar的高度

  • 安卓端statusBar通常是25dp,虚拟按键通常是48dp

  • 解决方法有四:

    • 设置view的高度是整屏的高度减去statusBar的高度
    • 设置top值为负的statusBar的高度
    • 设置bottom: -Dimensions.get('window').height 替代top: 0
    • 在每一个Navigator的入口设置<StatusBar translucent={true}/>
  • 大坑: 有些手机通过上述方法获取到的屏幕高度竟然包含了虚拟按键的高度,如魅族pro4,只能引入react-native-device-info这个库来hack一下了

3. Android过门动画卡顿

  • 从测试结果来看是网络请求和过门动作同时进行导致,将网络请求延迟到过门动画结束后即可解决。深层原因?

4. Android启动图launcher

  • 修改MainActivity的父类ReactActivity,在加载RN的view的同时在该view上面覆盖一个原生的view,用来显示启动图,并且设置N秒后隐藏或等待拿到首页数据接口后隐藏

5. 支持程度问题

  • iOS支持7.0及以上
  • Android支持API 16+ (Android 4.1) 因为使用了Choreographer
  • 友盟2016-02数据:
    • iOS7.0 以下已不计入主流版本(1%以下),和其他非主流版本共占4.92%
    • Android4.0 还有2.16%,其他非主流版本共占7.47%

About

React Native 双平台差异及解决方法