目录
- 两种像素
- 分辨率
- RN如何做屏幕适配
- 1. 尺寸相同,适配不同分辨率
- 2. 分辨率相同,适配不同尺寸屏幕
- 3. px转dp
- 4. 总结
- 最终适配方案
- 尺寸优化
- 1. 像素对齐
- 2. 实现真正的1px的分割线
- 3. dp转px
2倍屏,3倍屏,px,dp,这些概念因为不影响开发没有深入研究过,最近要写一个屏幕的工具类,就趁着这个机会彻底了解一下。
两种像素
- 物理像素:
单位是
px
,是画面中最小的点(单位色块)。像素的大小是没有固定长度值,不同分辨率设备上1个单位像素色块的大小是不一样的。
px在任何情况下都代表物理像素
- 逻辑像素
逻辑像素的单位有多种,
dp
是其中之一,如下栗子指的都是6寸的屏幕:
在非Retina屏, 1dp == 1px : 1寸宽有100个像素点
在2倍Retina屏,1dp == 2px : 1寸宽有200个像素点
在3倍Retina屏,1dp == 3px : 1寸宽有300个像素点
- DPR
DPR(设备像素比率) = px(物理像素)/dp(逻辑像素)
在每英寸160点的显示器上,1dp = 1px,设计师一般会以该基准作图
分辨率
- 屏幕上共有多少像素点,例如:屏幕分辨率是1024×768,也就是说设备屏幕的水平方向上有1024个像素点,垂直方向上有768个像素点
- iOS默认的单位是pt,android默认单位是dp,这两都是逻辑像素,在绘制时会自动转化为物理像素
RN如何做屏幕适配
1. 尺寸相同,适配不同分辨率
因为RN默认单位是dp,不需要考虑这个因素,系统会根据DPR(设备像素比率)
自动将dp转化成相应的物理像素值,比如:1dp,在2倍屏上被转化成2px,在3倍屏上被转化成3px,如下图
由此可得出如下两个结论:
- 尺寸固定,分辨率越高,像素点越小,内容就越清晰
- 尺寸固定,不同分辨率1dp的宽度值时一致的
补充:前端不支持dp/pt单位,起到类似作用的是rem,rem的思路跟上面一致,但那个转换过程需要自己手动配置
2. 分辨率相同,适配不同尺寸屏幕
此时因为分辨率相同所以像素个数也相同,但每px的尺寸相对于屏幕宽的比例是一致的,如下图:
由此可得出如下两个结论:
- 同分辨率下,虽然设置设备尺寸不同但1px相对于屏幕的比例却是一样的,如上图所示1dp都是屏幕的1/4,这正好符合我们的屏幕适配的定义
- 同分辨率下,尺寸越大,单位像素尺寸越大,内容越模糊
3. px转dp
前端朋友可能更习惯于px,需要将px转为dp
/* 转换公式
*
* deviceWidth是RN获取到的屏幕宽,单位是dp
* UI设计稿的宽度为750px
* size就是设置的px值
*
* 前面的除法得到在当前设备上每1px等于多少dp
*/
deviceWidth / 750 * size
可能有朋友迷糊了,为啥要用750呢,这个取决于你们UI给的设计稿的宽度,如果设计稿为375,那么就除以375
4. 总结
在RN中,dp单位解决了适配分辨率的问题;dp最后转化的px解决了适配不同尺寸的问题;最后的px转dp解决了前端经常使用的单位问题
最终适配方案
function px(size) {
if (size == 1) {
return StyleSheet.hairlineWidth;
}
return PixelRatio.roundToNearestPixel(deviceWidth / 750 * size);
}
尺寸优化
1. 像素对齐
当设置的像素值是小数时,会导致在GPU渲染时,对没对齐的边缘,需要进行插值计算,这个插值计算的过程会有性能损耗,所以要用到PixelRatio.roundToNearestPixel
方法
将布局大小(dp)四舍五入为与整数个像素对应的最近布局大小。例如,在PixelRatio为3的设备上PixelRatio.roundToNearestPixel(8.4) = 8.33,它恰好对应于(8.33 * 3)= 25像素
不是将dp转化为px
2. 实现真正的1px的分割线
若设置1dp,在1倍2倍3倍屏上分别渲染的真正像素分别是:1px,2px,3px,结果也不是我们想要的。
解决方式就是,当想要设置1px的线宽时,直接返回StyleSheet.hairlineWidth
- 当前平台上的最细的宽度。可以用作边框或是两个元素间的分隔线
- 该值并不是一个常量,他的单位是dp,但在不同分辨率上最后渲染出来的始终是1px的物理像素
3. dp转px
// 将布局大小(dp)转换为像素大小(px),保证返回一个整数
PixelRatio.getPixelSizeForLayoutSize(dp)