ReactNative也是以dp为单位的,这种单位会导致界面变形
先上界面布局
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
Text>
<Text style={styles.instructions}>
To get started, edit App.js
Text>
<Text style={styles.instructions}>
{instructions}
Text>
View>
);
}
首先看传统的写法
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 30,
textAlign: 'center',
margin: 10,
},
instructions: {
fontSize: 30,
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
在两个屏幕上的样子,左边是720 1080,右边是1080 1920,可以看到对比图
可以看出在不同的屏幕上展示的根本不一致
解决方案——百分比适配,先看代码
/**
* Created by qianxin on 17/6/1.
* 屏幕工具类
* ui设计基准,iphone 6
* width:750
* height:1334
*/
let ReactNative = require('react-native');
// 获取屏幕的dp
let Dimensions = require('Dimensions');
let screenW = Dimensions.get('window').width;
let screenH = Dimensions.get('window').height;
let fontScale = ReactNative.PixelRatio.getFontScale();
let pixelRatio = ReactNative.PixelRatio.get();
// 高保真的宽度和告诉
const designWidth = 750.0;
const designHeight = 1334.0;
// 根据dp获取屏幕的px
let screenPxW = ReactNative.PixelRatio.getPixelSizeForLayoutSize(screenW);
let screenPxH = ReactNative.PixelRatio.getPixelSizeForLayoutSize(screenH);
/**
* 设置text
* @param size px
* @returns {Number} dp
*/
export function setSpText(size:Number) {
console.log("screenW======"+screenW)
console.log("screenPxW======"+screenPxW)
var scaleWidth = screenW / designWidth;
var scaleHeight = screenH / designHeight;
var scale = Math.min(scaleWidth, scaleHeight);
size = Math.round(size * scale/fontScale + 0.5);
return size;
}
/**
* 设置高度
* @param size px
* @returns {Number} dp
*/
export function scaleSizeH(size:Number) {
var scaleHeight = size * screenPxH / designHeight;
size = Math.round((scaleHeight / pixelRatio + 0.5));
return size;
}
/**
* 设置宽度
* @param size px
* @returns {Number} dp
*/
export function scaleSizeW(size:Number) {
var scaleWidth = size * screenPxW / designWidth;
size = Math.round((scaleWidth/pixelRatio + 0.5));
return size;
}
这里面有一个核心API:PixelRatio,具体可以参看官方文档
上面的解决方案就是按照宽(高)度(px)*宽(高)度缩放的比例/设备的像素密度,这样就能精准的得到在相应的屏幕上想要的尺寸。
我们把上面的style稍微改一下,代码如下
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: setSpText(40),
textAlign: 'center',
margin: 10,
},
instructions: {
fontSize: setSpText(40),
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
再看运行的效果:
可以看出这样的话,在屏幕上显示效果就统一了
上面看的是字体的大小,我们在看一下宽高的情况,我们将外部container的height改为300
container: {
height:300,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FF0000',
},
然后我们将运用scaleSizeH进行处理,代码如下:
container: {
height:scaleSizeH(700),
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FF0000',
},
可以看出经过上述的处理方法,不同的屏幕展示的99%是一样的。
总结:RN的屏幕适配也有着和android一样的痛点,在这里实际上是实现了百分比布局,直接按照高保真所见即所得就可以高度还原界面,并且不需单位换算,直接按照高保真写px就可以了,也节省了效率(安卓也是可以在不影响性能的情况下根据高保真直接在xml填写px进行布局的),当然现实开发中,还是会遇到一些特殊的情况,需要特殊对待,上述屏幕适配工具栏还需要进一步完善,to be continued