搞不懂 px、dpi 和 dp?看这一篇就够了:图解 RN 屏幕适配逻辑
一、三个概念:px、dpi、dp
-
px:物理像素 / 分辨率里的那个像素 当我们说“720p、1080p”时,其实说的是分辨率:
- 720p ≈ 1280 × 720 像素
- 1080p ≈ 1920 × 1080 像素 这里的“1280、1920、720、1080”,都是 px(物理像素点的个数)。
-
dpi:像素密度(每英寸多少个像素) dpi(dots per inch)表示:一英寸(2.54cm)长度上有多少个像素点。
- 160dpi:每英寸约 160 个像素
- 320dpi:每英寸约 320 个像素(比 160dpi 更细腻) dpi 是硬件属性,跟屏幕多大、分辨率多少一起决定“看起来多清晰”。
-
dp:密度无关像素(React Native 用的逻辑单位) dp(density-independent pixel)是系统定义的一种“逻辑长度单位”,让同样的数值在不同 dpi 的设备上,看起来差不多大。 在 React Native 里,你写
width: 100,这个 100 本质上就是 100dp,而不是 100px。
二、dp 和 dpi 的数学关系
Android / React Native 的约定:
- 把 160dpi 的屏幕当成基准屏幕。
- 在 160dpi 屏幕上:
1dp ≈ 1px - 在其它密度屏幕上,系统用这个公式换算:
px = dp × (dpi / 160)
举几个数字例子:
-
160dpi(基准)
1dp = 1 × (160 / 160) = 1px100dp = 100px -
320dpi
1dp = 1 × (320 / 160) = 2px100dp = 200px -
480dpi
1dp = 1 × (480 / 160) = 3px100dp = 300px(四舍五入后近似)
也就是说:
当你在代码里写 width: 100 时,这个 100 实际上是 100dp。系统会根据当前设备的 dpi,把它换算成应该使用多少个物理像素:
- 在 160dpi 的屏幕上,大约使用 100px(1dp ≈ 1px);
- 在 320dpi 的屏幕上,大约使用 200px(1dp ≈ 2px);
- 在 480dpi 的屏幕上,大约使用 300px(1dp ≈ 3px)。
随着屏幕像素密度提高,单个像素本身变得更小,所以虽然不同设备实际使用的物理像素数量不一样,但这个“100dp 宽”的控件在现实世界里的物理尺寸(比如看起来有多宽、占多大一块屏幕)会尽量保持接近。
现在,160/320/480dpi 和 dp→px 的关系就理清楚了,也解释了“为什么同样的 dp 在不同手机上看起来差不多大”。
三、示意图:同样 100dp 的按钮,在不同 dpi / 分辨率上长什么样?
1)左边:720p,160dpi
- 分辨率:1280 × 720 px
- dpi:160
- 换算:
1dp = 1px,100dp = 100px - 按钮在屏幕上大约占据“某个具体宽度 A 厘米”。
2)中间:1080p,320dpi
- 分辨率:1920 × 1080 px
- dpi:320(像素更密)
- 换算:
1dp = 2px,100dp = 200px - 按钮用更多像素画出来,但因为像素更小,实际占据的物理宽度依然接近 A 厘米。
3)右边:更高分辨率,2K,480dpi
- 分辨率:例如 2560 × 1440 px
- dpi:480
- 换算:
1dp = 3px,100dp = 300px - 按钮在屏幕上依然大约是 A 厘米宽,只是边缘、文字更细腻。
图中三个按钮,看起来差不多宽,但右边那台的像素数量最多——这就是“dp + dpi 换算”的效果:同样的 dp 值,在高密度屏上用更多 px 去画,从而保持视觉尺寸接近。
四、那 720p、 1080p 在这个故事里扮演什么角色?
- 720p、1080p 说明的是总像素数(分辨率),即屏幕一共多少个 px。
- dpi 说明的是这些像素在物理尺寸上的“密度”,和“屏幕有多大”一起决定屏幕看起来多清晰。
- dp 是在 React Native / Android / iOS 布局里用的“逻辑尺寸单位”,用来写 UI 尺寸。系统会根据当前设备的 dpi 和分辨率,用公式把 dp 换成 px。
你可以大致这样理解:
- px:砖头总数(分辨率)
- dpi:每 1cm 摆多少块砖(密度)
- dp:设计图上画的“这堵墙要 2 米宽”,具体到现场要用多少砖,由工人(系统)根据砖尺寸(dpi)来算。
五、在 React Native 里怎么用 dp 写尺寸?
在 RN 代码里,你不用写 dp、px 这样的单位,直接写数字即可,这个数字默认就是 dp:
// 宽高都是 dp 单位
<View style={{ width: 100, height: 40, borderRadius: 8 }} />
React Native 会做几件事:
- 获取当前设备的:
- 分辨率(总px数)
- 屏幕尺寸(英寸)
- 像素密度dpi(ppi)
- 用公式
px = dp × (dpi / 160),把你的dp换算成真实px - 把这个px告诉底层原生视图去渲染
你也可以用 Dimensions 和 PixelRatio 看一下当前设备的逻辑尺寸和像素比:
import { Dimensions, PixelRatio } from 'react-native';
const { width, height } = Dimensions.get('window'); // 宽高,单位是 dp
const pixelRatio = PixelRatio.get(); // 设备像素比,约等于 dpi / 160
比如某台设备:
- width = 375,height = 812(单位是逻辑尺寸dp)
- pixelRatio = 3
- 分辨率大约是:宽 375 × 3 = 1125px,高 812 × 3 ≈ 2436px(类似iPhoneX)
六、和设计稿的连接:从px到dp
在开发中,你最困惑的可能是: “设计师给我一张 750px 宽的图,我为什么要写 375?”
为什么要“除以 2”?
这得从移动端设计的行业标准说起。
1. 什么是“2 倍图”?
在 Retina(视网膜)屏幕出现之前,屏幕很渣(1倍屏),1个逻辑像素 = 1个物理像素。
后来 iPhone 4 搞出了 Retina 屏,屏幕大小没变,但塞进去的像素翻了一倍(横竖各翻倍)。
这就出现了一个标准: “2 倍图标准” (以 iPhone 6/7/8 为基准):
- 手机物理屏幕(硬件): 宽 750px(很细腻)。
- 系统逻辑宽度(软件): 宽 375dp(也就是系统认为只有 375 个“点”)。
- 关系: 750 ÷ 375 = 2。这就是 “2 倍图” (@2x) 的由来。即:2 个物理像素 = 1 个逻辑点 (dp) 。
2. 设计师为什么喜欢给 750px 的稿子?
虽然系统逻辑只要 375dp,但为了保证图标、线条在高通过率屏幕上不模糊,设计师通常会在 750px × 1334px(也就是 iPhone 6/7/8 的物理分辨率)的画布上画图。
这就好比:设计师在一张很大、很清晰的纸(750px)上画图,但你的手机屏幕是一个缩小镜,它要把这张大纸缩放到 375dp 的逻辑宽度里去显示。
3. 开发者怎么换算?(核心公式)
因为 RN 代码里写的是 dp(逻辑点),而设计稿是 px(物理像素,且通常是 2 倍密度的)。
所以,拿到一张 750px 宽 的设计稿,你的换算逻辑是:
RN 数值 = 设计稿数值 ÷ 2
实战例子:
-
场景:设计师用 Figma 给了一张 750px 宽的设计稿。
-
元素 A:设计稿上量出来宽 200px。
- 你的思考:这是 2 倍图,所以我除以 2。
-
代码写:
width: 100
-
元素 B:设计稿上量出来字号 32px。
- 你的思考:除以 2。
-
代码写:
fontSize: 16
4. 特殊情况:如果是 3 倍图呢?
现在有的设计师喜欢用 iPhone 12/13/14 Pro 的尺寸做图,这类手机的画布宽度通常是 1125px 或者更高。
- 基准逻辑宽度:依然约等于 375dp ~ 390dp。
- 换算关系:1125 ÷ 375 = 3。
- 结论:如果设计师给你的是 3 倍图(超高清稿),你就 除以 3。
开发建议:
可以问设计师一句:“你这是按几倍图画的?”
- 如果是按 750px 宽画的,就是 2 倍图 -> 除以 2。
- 如果是按 375px 宽画的(1 倍图),就是 1 倍图 -> 不除,是多少写多少。 这两个部分是文章的点睛之笔。为了吸引读者点击并帮助他们快速消化内容,我为你准备了几个不同风格的标题和一个核心总结。
总结
React Native 开发中,为了让 App 在不同手机上看起来一样大,我们使用 dp(逻辑点) 而不是 px(物理像素);而连接设计稿(px)与代码(dp)的关键,通常在于除以 2。
详细总结:
-
概念分层:
- px (物理像素) 是屏幕上发光的“灯泡”总数(如 1080p),决定了屏幕有多大(分辨率)。
- dpi (像素密度) 是“灯泡”排得有多密,决定了屏幕有多清晰。
- dp (逻辑单位) 是 RN 代码用的单位,系统会根据 dpi 自动把它换算成 px,保证视觉尺寸一致。
-
核心换算:
- 系统渲染公式:
px = dp × (dpi / 160)。 - 100dp 在低清屏上可能是 100px,在高清屏上可能是 200px 或 300px,但物理宽度(厘米)始终保持一致。
- 系统渲染公式:
-
开发实战:
- 设计稿通常基于 iPhone 6/7/8 标准(750px 宽,2 倍图)。
- 因此,看到设计稿上的 px 数值,代码里写 dp 时通常除以 2(例如:稿子宽 200px → 代码写
width: 100)。 - 口诀: 问清倍率再动手,2 倍图除以 2,3 倍图除以 3。