3

React Native 屏幕适配

 1 year ago
source link: https://neulionweb.dev/2022/03/react-native-design-match
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

React Native 屏幕适配

设计稿使用px, React Native 无单位,用的设备逻辑单位pt/dp。如何适配不同设备屏幕尺寸以及不同分辨率?

一些基础概念

pt vs dp

  • 相同点:
    都是为了适配不同屏幕不同尺寸的移动设备而设计出来的一种单位,用于表示UI布局尺寸与设备屏幕密度无关。所以又叫密度无关像素或者密度独立像素。(Chrome debug模式下的设备模拟器,看到的就是这个尺寸)
  • 不同点:
    pt是iOS设备的布局尺寸单位,苹果公司给的定义是:1pt = 1/163 inch,dp是android设备的布局尺寸单位,Wikipedia给的定义对于android设备:1dp = 1/160 inch; 像素(pixels)和二者的转换关系不同:iOS pt = pixels * ( ppi/163)、Android dp = pixels * (ppi/160)

屏幕尺寸:屏幕对角线的长度,比如iPhoneX是5.8英寸。(英寸:inch,1英寸=2.54厘米) dpi/ppi:屏幕密度,每英寸的点数/每英寸的像素值。(比如 320ppi表示每平方英寸有320 * 320 个 px) ppi=x2+y2屏幕尺寸

分辨率:屏幕上物理像素的总数,横向和纵向的像素值 比如 iPhoneX的分辨率是 1125px* 2436px

如何理解React Native是无单位的?
首先是因为 React Native 是跨平台的,iOS的逻辑像素单位是 pt,Android的逻辑像素单位是 dp,没办法兼顾,就直接去掉了,运行在哪个平台,就用哪个平台的单位。 RN 提供的就是 逻辑像素单位,是和像素密度无关的,RN本身会根据像素密度做适配,渲染对应的物理像素。

场景:布局

整体布局一般采用Flex 弹性布局。特别的全屏布局或百分比布局,利用 屏幕宽度/高度 计算而来,

const {deviceWidth, deviceHeight} = Dimensions.get('window');
width: deviceWidth * 0.7; 

比如整个页面的布局是header,footer 固定height,中间自适应. 中间区域可以利用高度计算而来。

layout

比如这个item row的布局,目前用的是flex, 1:3:1:1:1

layout

场景:盒模型

局部盒模型元素,进行宽度适配,保证页面元素大小按照设计稿尺寸进行等比例缩放。(盒模型中的width,height,padding,margin…)

举例:
设计稿:整体尺寸 1920px * 1080px. 设计了一个元素 640px * 540px(蓝色区域)

design
//获取设备dp
const designTotalWidth = 1920; // 设计稿尺寸 1920px*1080px
const {deviceWidth, deviceHeight} = Dimensions.get('window');
//设计稿上一个 640px*540px 的区域。CSS
{
    width:   (640/designTotalWidth) * deviceWidth
    height:  (540/designTotalWidth) * deviceWidth
}

来看实际情况

设备 React Native CSS Device UI
设备(1080P) 960dp * 540dp,分辨率1920 *1080, density 320dpi, xhdpi, 像素密度 2 根据公式:width: 320,height: 270
device result
设备(4K) 960dp * 540dp,分辨率 3840 *2160, density 640dpi, xhdpi, 像素密度 4 根据公式:width: 320,height: 270
device result

结论蓝色盒子始终是整个屏幕的⅙ ,宽度是整个屏幕的 ⅓,高度是½. 实现了屏幕适配。这个解决方案会最大限度的保留设计图的大小与布局设计效果。

比如红色区域的宽高,黄色区域的宽度

layout

进阶抽离 将 px2dp 等比例转化方法提取出来,按需使用。 这里也有一种方案是整体做了处理,缺点是内部一些特别的元素无法区别开

场景:图片

准备多个分辨率尺寸的图片,通过设备的像素密度比,拿到最适合的图片进行显示

const image = getImage({
  width: PixelRatio.getPixelSizeForLayoutSize(200),//如果当前的设备 pixelratio 为2,则返回 width:400, height:200
  height: PixelRatio.getPixelSizeForLayoutSize(100),// 等同于 100 * PixelRatio.get()
});
<Image source={image} style= />

参考官网:https://reactnative.cn/docs/pixelratio

场景:字体

  1. 需要根据设备字体缩放比例

    利用 getFontScale(), Android 返回设备设置的字体缩放比例,iOS 返回默认的像素密度 fontSize: 12 * getFontScale();

  2. 根据设备屏幕大小自适应

    有很多的换算方法,总的来说,要么根据像素密度比,要么根据屏幕缩放比,要么根据屏幕尺寸分区。参考这里

  3. 需要自适应父容器的高宽

    <View style={height:100,width:200}>
          <Text style= adjustsFontSizeToFit={true}>
              Example of adjustsFontSizeToFit True in React Native
           </Text>
    </View>
    
    layout

进阶抽离
可以写一个custom Text,在内部进行字体大小转换,返回原生 Text。

思考对于字体的问题,从用户体验来说用户心愿看到的字体是相对大小的,就像看报纸,多大张的报纸,字体都应该是一样大,有一个最适宜浏览的字体大小,而自适应突破了这种设计哲学。

场景:边框或线条

边框和线条一般要求所有屏幕保持相同的px 显示,比如需要看到一条最细的边框线。

borderWidth: 1/PixelRatio.get()
layout

像素精度
比如设计稿上有个尺寸 width: 8.6 我们应该如何使用? 折算到匹配整数像素的 dp 尺寸

width: PixelRatio.roundToNearestPixel(8.4) 

不同设备屏幕尺寸

在进行 Web UI开发时,我们一般会针对不同的区间做响应式设计,不同的区间在设计上也会有一些区别。 USGA实际上设计了两个区间 phone 和 TV,但我们并没有以逻辑像素来判断,用的是上层给的 mode

主流机顶盒

主流宽度:1920,1280,960

宽 * 高 dp dpi
1920 * 1080 dpi=1.0 mdpi
1920 * 1080 dpi=1.5 hdpi
1920 * 1080 dpi=2 xhdpi
1280 * 720 dpi=1.0 mdpi
1280 * 720 dpi=1.5 hdpi
960 * 540 dpi=2.0 xhdpi
960 * 540 dpi=4.0 xxhdpi

实践
USGA

  • Phone mode.
    看mobile的设计稿,给的是 375px * 646px, 我们测试的mobile 设备iphone 11 1792px * 828px, 像素密度 326/160。设备像素无关分辨率 896 * 414 目前方案:直接使用的设计稿尺寸。因为设计稿尺寸与设备的dp区间基本一致。
  • TV mode.
    看TV的设计稿,给的是 1920px * 1080px,我们测试的TV设备 (Android TV 1080P),屏幕分辨率 1920px * 1080px,像素密度 2。设备像素无关分辨率 960dp * 540dp
    设计稿尺寸与设备的实际dp区间不一致。 目前方案:对盒模型的尺寸除以像素密度比,如
    width: 40 / PixelRatio.get()
    

    完成的效果是,不同分辨率和不同屏幕大小的设备下,宽度始终是 40px。所以在低密度上看起来比较大,高密度上看起来比较小。

最佳实践:按照上面的结论,边框和线条继续使用这种方式,其他盒模型的尺寸等比例缩放。

(转载本站文章请注明作者和出处 NeuLion Web

Related Issues not found

Please contact @cammytang @helloint to initialize the comment


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK