搞不懂 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 倍图 -> 不除,是多少写多少
相关推荐
程序员爱钓鱼1 小时前
使用 Node.js 批量导入多语言标签到 Strapi
前端·node.js·trae
鱼樱前端1 小时前
uni-app开发app之前提须知(IOS/安卓)
前端·uni-app
V***u4531 小时前
【学术会议论文投稿】Spring Boot实战:零基础打造你的Web应用新纪元
前端·spring boot·后端
i听风逝夜1 小时前
Web 3D地球实时统计访问来源
前端·后端
iMonster2 小时前
React 组件的组合模式之道 (Composition Pattern)
前端
呐呐呐呐呢2 小时前
antd渐变色边框按钮
前端
元直数字电路验证2 小时前
Jakarta EE Web 聊天室技术梳理
前端
wadesir2 小时前
Nginx配置文件CPU优化(从零开始提升Web服务器性能)
服务器·前端·nginx
牧码岛2 小时前
Web前端之canvas实现图片融合与清晰度介绍、合并
前端·javascript·css·html·web·canvas·web前端