Appearance
布局约束与尺寸单位
ArkTS 中的尺寸单位系统、约束类型、对齐方式等布局基础概念。
1. 尺寸单位总览
| 单位 | 全称 | 说明 | 适用场景 |
|---|---|---|---|
| vp | Virtual Pixel | 逻辑像素,根据 DPI 自动适配 | 宽度/高度/间距(推荐) |
| fp | Font Pixel | 字体像素,根据系统字体缩放 | 字号(推荐) |
| px | Physical Pixel | 物理像素,不随 DPI 变化 | 边框宽度(谨慎使用) |
| % | Percentage | 占父容器的百分比 | 响应式布局 |
| auto | Automatic | 自动适配 | 容器宽度/高度 |
| match_parent | 匹配父容器 | 等同于 '100%' | 全宽/全高 |
2. vp — 逻辑像素
2.1 概念
vp = dp = dip(Density-independent Pixel)
不同设备的物理像素(px)不同,但 vp 在视觉上是相同的
320px 的设备:1vp = 1px(DPI=160)
480px 的设备:1vp = 1.5px(DPI=240)
640px 的设备:1vp = 2px(DPI=320)2.2 使用示例
typescript
// ✅ 推荐用 vp
Image('icon.png')
.width(48vp) // 图标大小
.height(48vp)
Text('标题')
.fontSize(24vp) // ❌ 字号不应用 vp,应该用 fp
.width(200vp) // ✅
Button('提交')
.width('100%') // ✅ 响应式宽度
.height(48vp) // ✅ 固定高度3. fp — 字体像素
3.1 概念
fp = 根据系统字体大小自动缩放的字体像素
用户修改系统字体大小 → fp 自动适配
用户修改系统字体大小 → vp 不变3.2 使用规范
typescript
// ✅ 字号统一用 fp
Text('大标题')
.fontSize(32fp)
Text('正文')
.fontSize(16fp)
Text('辅助文字')
.fontSize(12fp)
// ❌ 字号不用 vp 或 px
Text('标题')
.fontSize(24vp) // ❌ 不随系统字体缩放4. px — 物理像素
4.1 什么时候用 px?
typescript
// ✅ 边框宽度:需要精确到 1 个物理像素
Row() {
Text('左边')
Divider()
.strokeWidth(1px) // ✅ 1px 细边框
Text('右边')
}
// ❌ 其他场景不要用 px
Image('icon')
.width(24px) // ❌ 不同设备上显示大小不同5. 约束类型
5.1 宽度约束
| 约束 | 语法 | 说明 |
|---|---|---|
| 固定宽度 | width(100) | 固定 100vp |
| 百分比 | width('50%') | 占父容器的 50% |
| 全宽 | width('100%') | 占满父容器 |
| 自动 | width('auto') | 根据内容自适应 |
| 填充 | width('match_parent') | 同 '100%' |
5.2 高度约束
| 约束 | 语法 | 说明 |
|---|---|---|
| 固定高度 | height(60) | 固定 60vp |
| 最小高度 | .minHeight(50) | 最小 50vp |
| 最大高度 | .maxHeight(200) | 最大 200vp |
| 百分比 | height('50%') | 占父容器的 50% |
6. 对齐方式
6.1 主轴对齐(Row → 水平,Column → 垂直)
typescript
Row() {
Text('A')
Text('B')
Text('C')
}
.justifyContent(FlexAlign.Start) // 左对齐(Row)/ 顶对齐(Column)
.justifyContent(FlexAlign.Center) // 居中
.justifyContent(FlexAlign.End) // 右对齐(Row)/ 底对齐(Column)
.justifyContent(FlexAlign.SpaceAround) // 每个元素两侧间距相等
.justifyContent(FlexAlign.SpaceBetween) // 两端对齐,间距相等6.2 交叉轴对齐(Row → 垂直,Column → 水平)
typescript
Row() {
Text('A')
.height(100) // A 更高
Text('B')
.height(50)
Text('C')
.height(75)
}
.alignItems(VerticalAlign.Start) // 顶部对齐
.alignItems(VerticalAlign.Center) // 垂直居中
.alignItems(VerticalAlign.End) // 底部对齐
.alignItems(VerticalAlign.Baseline) // 基线对齐7. 边距与内边距
7.1 margin(外边距)
typescript
Text('Hello')
.margin({
top: 10,
bottom: 10,
left: 15,
right: 15
})
// 快捷写法
Text('Hello')
.margin(10) // 四周
.margin({ top: 10 }) // 仅上边
.margin({ left: 10, right: 10 }) // 左右7.2 padding(内边距)
typescript
Button('点击')
.padding({
top: 10,
bottom: 10,
left: 20,
right: 20
})8. 尺寸计算的优先级
优先级(从高到低):
1. 固定值(如 width(100))
2. 百分比(如 width('50%'))
3. 内容自适应(auto/match_parent)
4. flex 权重分配(flexGrow)冲突解决
typescript
// ❌ 冲突:width 同时设置了固定值和百分比
Row() {
Text('A').width(100).width('50%') // 后者覆盖前者
}
// ✅ 正确:在不同组件上用不同约束
Row() {
Text('固定')
.width(100) // 固定宽度
Blank() // 填充中间
Text('自适应')
.width('100%') // 百分比宽度
}9. 单位转换工具
9.1 getFontScale()
typescript
import { window } from '@kit.ArkUI'
// 获取系统字体缩放比例
let fontScale = window.getWindowExtension().getFontScale()
// 手动将 vp 转换为 fp
function vpToFp(vp: number): number {
return Math.round(vp * fontScale)
}9.2 单位选择指南
| 元素 | 推荐单位 | 原因 |
|---|---|---|
| 宽度/高度 | vp | 适配不同 DPI |
| 字号 | fp | 适配系统字体缩放 |
| 边框 | px | 精确像素 |
| 间距/边距 | vp | 视觉一致性 |
| 响应式宽度 | % | 自适应 |
10. 面试高频考点
Q1: vp、fp、px 的区别?
回答:
- vp:逻辑像素,根据 DPI 自动适配,用于宽/高/间距
- fp:字体像素,根据系统字体缩放,用于字号
- px:物理像素,不随 DPI 变化,仅用于边框宽度
Q2: Blank 组件的作用?
回答:在 Row/Column 中自动填充剩余空间,常用于"左边文字-右边图标"的两端对齐布局,或把内容推到屏幕底部。
Q3: justifyContent 有哪些对齐方式?
回答:Start、Center、End、SpaceAround、SpaceBetween。Row 对应水平方向,Column 对应垂直方向。
🐱 小猫提示:单位选择记住口诀——"宽高用 vp,字号用 fp,边框用 px,响应用 %"。这是面试中最基础的题。