阅读视图

发现新文章,点击刷新页面。

搞不懂 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 / 分辨率上长什么样?

Gemini_Generated_Image_hl6v29hl6v29hl6v.png1)左边: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:

// 宽高都是 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 看一下当前设备的逻辑尺寸和像素比:

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

详细总结:

  1. 概念分层:

    • px (物理像素) 是屏幕上发光的“灯泡”总数(如 1080p),决定了屏幕有多(分辨率)。
    • dpi (像素密度) 是“灯泡”排得有多,决定了屏幕有多清晰
    • dp (逻辑单位) 是 RN 代码用的单位,系统会根据 dpi 自动把它换算成 px,保证视觉尺寸一致。
  2. 核心换算:

    • 系统渲染公式:px = dp × (dpi / 160)
    • 100dp 在低清屏上可能是 100px,在高清屏上可能是 200px 或 300px,但物理宽度(厘米)始终保持一致。
  3. 开发实战:

    • 设计稿通常基于 iPhone 6/7/8 标准(750px 宽,2 倍图)。
    • 因此,看到设计稿上的 px 数值,代码里写 dp 时通常除以 2(例如:稿子宽 200px → 代码写 width: 100)。
    • 口诀: 问清倍率再动手,2 倍图除以 2,3 倍图除以 3。
❌