核心目标:解决“碎片化”屏幕尺寸问题。
适用人群:iOS/Android/鸿蒙原生开发者、前端工程师。
核心价值:理解 uni-app 如何通过单位转换和 Flex 布局,在 iPhone 15 Pro Max、华为 Mate 60、微信小程序等不同终端上实现像素级一致的视觉还原。
一、 核心适配方案:尺寸单位
在原生开发中,iOS 使用 pt,Android 使用 dp/sp,鸿蒙使用 vp/fp。而在 uni-app 中,为了实现“一次编写,多端运行”,核心适配单位是 rpx。
1. 什么是 rpx (responsive pixel)?
rpx 是 uni-app 独有的响应式像素单位。它的设计哲学与微信小程序一致,旨在解决不同屏幕宽度下的等比缩放问题。
-
基准规则:规定屏幕宽度为 750rpx。
-
换算逻辑:
- 在 iPhone 6/7/8 (屏幕宽度 375px) 上:
750rpx = 375px = 750物理像素。即1rpx = 0.5px = 1物理像素。 - 在 iPhone 6 Plus (屏幕宽度 414px) 上:
750rpx = 414px。 - 在 Android 设备上:会根据实际屏幕宽度进行线性换算。
- 在 iPhone 6/7/8 (屏幕宽度 375px) 上:
实战建议:UI 设计师通常提供 750px 宽度的设计稿(对应 iPhone 6/7/8 的 2 倍图)。此时,设计稿上标注多少 px,代码里直接写多少 rpx 即可(1:1 还原)。
2. 单位对比表:原生 vs uni-app
| 维度 | iOS 原生 | Android 原生 | 鸿蒙 (HarmonyOS) | uni-app (推荐) | 说明 |
|---|---|---|---|---|---|
| 宽度单位 | pt | dp | vp | rpx | 随屏幕宽度等比缩放,保证布局比例一致 |
| 字体单位 | pt | sp | fp | rpx | 字体也随屏幕缩放(若需固定大小可用 px) |
| 物理像素 | pixel | px | px | px | 绝对像素,不推荐用于布局 |
3. 特殊单位:px 与 upx
-
px (像素) :
- 在 uni-app 中,
px是绝对单位,对应屏幕的物理像素(或逻辑像素,视平台而定)。 - 使用场景:绘制 1 像素的分割线(
border: 1px solid #ccc),或者不希望随屏幕宽度缩放的元素。 - 注意:在 App 端的
titleNView或原生插件中,只支持px。
- 在 uni-app 中,
-
upx:
upx是rpx的别名,两者完全等价。早期 uni-app 使用upx,现在官方推荐统一使用rpx以对齐小程序标准。
4. 响应式布局的“陷阱”与对策
虽然 rpx 能解决宽度适配,但在超宽屏幕(如 iPad 或折叠屏)上,如果完全使用 rpx,元素会被拉得非常大。
-
对策:uni-app 允许配置
rpx的计算上限。 -
配置:在
manifest.json中配置app-plus->rpxCalcMaxDeviceWidth。- 默认值通常是 960px。即当设备宽度超过 960px 时,rpx 的计算基准不再增加,保持 960px 时的比例,防止界面在大屏上过于稀疏。
二、 布局模式:Flexbox 是王道
在原生开发中,iOS 常用 AutoLayout/Masonry,Android 常用 LinearLayout/ConstraintLayout。在 uni-app 中,Flex 布局是跨端一致性最好的布局方案。
1. 为什么首选 Flex?
- 一致性:uni-app 的 Flex 实现基于 Web 标准,在 H5、小程序、App(Weex/Native 引擎)上的表现高度一致。
- 性能:原生渲染引擎对 Flex 有专门的优化。
- 避免 Float:不要使用
float,在小程序和 App 端支持极差。
2. 常用布局代码片段
/* 水平居中 + 垂直居中 */
.container {
display: flex;
justify-content: center; /* 主轴居中 */
align-items: center; /* 交叉轴居中 */
}
/* 左右结构:左侧固定,右侧自适应 */
.row {
display: flex;
}
.left {
width: 200rpx; /* 固定宽度 */
}
.right {
flex: 1; /* 占据剩余空间 */
}
三、 安全区域与系统适配 (刘海屏/底部Home条)
这是原生转前端最容易忽略的点。iPhone 的刘海、底部小黑条,Android 的挖孔屏,都需要预留安全距离。
1. 使用 CSS 变量 (推荐)
uni-app 内置了几个关键的 CSS 变量,用于处理系统 UI 的遮挡问题:
| 变量名 | 描述 | 典型应用场景 |
|---|---|---|
var(--status-bar-height) | 状态栏高度 | 自定义导航栏时,给顶部 View 设置 padding-top |
var(--window-top) | 内容区域距离顶部距离 | 处理非沉浸式场景 |
var(--window-bottom) | 内容区域距离底部距离 | 底部固定按钮,避开 Home Indicator |
代码示例:
<template>
<view class="header">
<!-- 这里的 padding-top 会自动适配 iPhone 刘海屏高度或 Android 状态栏高度 -->
<view class="status-bar-placeholder"></view>
<view class="nav-title">我的页面</view>
</view>
</template>
<style>
.status-bar-placeholder {
height: var(--status-bar-height);
width: 100%;
background-color: #ffffff;
}
.header {
width: 100%;
background-color: #ffffff;
}
</style>
2. 使用 uni.getSystemInfoSync() (JS 动态获取)
如果需要更精确的控制(例如在 Canvas 绘图或计算滚动高度时),可以通过 API 获取:
const systemInfo = uni.getSystemInfoSync();
const isIPhoneX = systemInfo.model.includes('iPhone X'); // 简单判断
const statusBarHeight = systemInfo.statusBarHeight; // 状态栏高度
const safeArea = systemInfo.safeArea; // 安全区域对象 {top, left, bottom, right}
四、 图片与字体适配
1. 背景图片
-
本地图片:在 CSS 中使用本地图片作为背景时,推荐使用
~@/static/...的绝对路径写法。 -
大小限制:小程序端对 CSS 中引入的本地图片有大小限制(通常 40kb 以下会自动转 Base64)。大图建议放在服务器上,使用网络路径。
-
写法:
.banner { /* 推荐写法,兼容性最好 */ background-image: url('~@/static/banner.png'); background-size: cover; }
2. 字体图标
- 推荐:使用阿里图标库(iconfont)生成的网络字体链接。
- 注意:小程序不支持本地字体文件(ttf),必须转为 Base64 或上传到 CDN 使用 HTTPS 链接。
五、 总结:跨端布局最佳实践清单
为了保证在 iOS、Android、鸿蒙、小程序上的一致性,请遵循以下规范:
-
布局单位:全局使用
rpx。- 例外:1像素边框使用
px。
- 例外:1像素边框使用
-
布局方式:全局使用
Flex。- 禁止:使用
float或复杂的绝对定位。
- 禁止:使用
-
顶部适配:自定义导航栏必须预留
var(--status-bar-height)的高度。 -
底部适配:底部固定按钮使用
padding-bottom: env(safe-area-inset-bottom)或var(--window-bottom)避开底部操作条。 -
设计稿:让 UI 设计师出 750px 宽度的设计稿,开发时数值直接照搬,单位换成 rpx。
-
字体:字体大小也建议使用
rpx,这样在大屏手机上字体也会适当放大,阅读体验更好(如果设计稿是 28px,代码写 28rpx)。
通过这套体系,uni-app 能够将复杂的原生适配逻辑抽象化,让开发者只需关注业务逻辑,即可实现“多端像素级还原”。