搞不懂 px、dpi 和 dp?看这一篇就够了:图解 RN 屏幕适配逻辑

一、三个概念:px、dpi、dp

  1. px:物理像素 / 分辨率里的那个像素 当我们说"720p、1080p"时,其实说的是分辨率:

    • 720p ≈ 1280 × 720 像素
    • 1080p ≈ 1920 × 1080 像素 这里的"1280、1920、720、1080",都是 px(物理像素点的个数)。
  2. dpi:像素密度(每英寸多少个像素) dpi(dots per inch)表示:一英寸(2.54cm)长度上有多少个像素点。

    • 160dpi:每英寸约 160 个像素
    • 320dpi:每英寸约 320 个像素(比 160dpi 更细腻) dpi 是硬件属性,跟屏幕多大、分辨率多少一起决定"看起来多清晰"。
  3. 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) = 1px 100dp = 100px
  • 320dpi 1dp = 1 × (320 / 160) = 2px 100dp = 200px
  • 480dpi 1dp = 1 × (480 / 160) = 3px 100dp = 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 = 1px100dp = 100px
  • 按钮在屏幕上大约占据"某个具体宽度 A 厘米"。

2)中间:1080p,320dpi

  • 分辨率:1920 × 1080 px
  • dpi:320(像素更密)
  • 换算:1dp = 2px100dp = 200px
  • 按钮用更多像素画出来,但因为像素更小,实际占据的物理宽度依然接近 A 厘米。

3)右边:更高分辨率,2K,480dpi

  • 分辨率:例如 2560 × 1440 px(举例)
  • dpi:480
  • 换算:1dp = 3px100dp = 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:

javascript 复制代码
// 宽高都是 dp 单位
<View style={{ width: 100, height: 40, borderRadius: 8 }} />

React Native 会做几件事:

  1. 获取当前设备的:
    • 分辨率(总px数)
    • 屏幕尺寸(英寸)
    • 像素密度dpi(ppi)
  2. 用公式 px = dp × (dpi / 160),把你的dp换算成真实px
  3. 把这个px告诉底层原生视图去渲染

你也可以用 DimensionsPixelRatio 看一下当前设备的逻辑尺寸和像素比:

js 复制代码
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 倍图 -> 不除,是多少写多少
相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax