Appearance
样式与属性
ArkUI 的属性系统:几何属性、位置属性、容器属性、文本样式、背景与边框。
1. 属性分类
属性
├── 几何属性:width/height/minWidth/maxWidth/...
├── 位置属性:position/top/left/right/bottom
├── 容器属性:justifyContent/alignItems/...
├── 文本属性:fontSize/fontColor/fontWeight/...
├── 背景属性:backgroundColor/backgroundImage
├── 边框属性:border/borderRadius
├── 阴影属性:boxShadow
├── 可见性:visibility/display
├── 动画属性:animation/clip
└── 事件属性:onClick/onLongClick/...2. 几何属性
2.1 宽度与高度
typescript
// 固定尺寸
Text('Hello')
.width(100) // 100vp
.height(50) // 50vp
// 百分比
Image('icon')
.width('50%') // 父容器的 50%
.height('auto') // 自动(保持比例)
// 约束
Text('文本')
.minWidth(50) // 最小宽度
.maxWidth(200) // 最大宽度
.minHeight(30) // 最小高度
.maxHeight(100) // 最大高度2.2 宽高比
typescript
// 保持 1:1 比例(正方形)
Image('icon')
.width(100)
.aspectRatio(1)
// 保持 16:9 比例(视频封面)
Video('cover')
.width('100%')
.aspectRatio(16 / 9)3. 位置属性
3.1 position — 绝对定位
typescript
// position 相对于父容器
Stack() {
Image('background')
.width('100%')
.height(200)
// 在父容器 (0,0) 位置放置
Text('左上')
.position({ x: 10, y: 10 })
// 在父容器右下角
Text('右下')
.position({ x: 'calc(100% - 60)', y: 'calc(100% - 30)' })
}
.width('100%')
.height(200)3.2 offset — 相对偏移
typescript
// 相对于自身原始位置偏移
Text('偏移文本')
.offset({ x: 10, y: -20 }) // 右移10,上移203.3 top/left/right/bottom
typescript
// 锚点定位
Image('icon')
.top(20) // 距顶部 20vp
.right(10) // 距右侧 10vp4. 文本样式属性
typescript
Text('多行文本样式演示')
.fontSize(24fp) // 字号
.fontColor(Color.Blue) // 文字颜色
.fontWeight(FontWeight.Bold) // 字重(Normal/Medium/Bold)
.fontStyle(FontStyle.Italic) // 斜体
.letterSpacing(2) // 字间距
.lineHeight(36fp) // 行高
.textAlign(TextAlign.Center) // 对齐方式
.maxLines(2) // 最大行数
.textOverflow({ overflow: TextOverflow.Ellipsis }) // 溢出显示 ...
.fontFeatures([ // 字体特性
FontFeature.LIGATURES, // 连字
FontFeature.SMALL_CAPS // 小型大写字母
])
.textDecorations([ // 文字装饰
{ type: TextDecorations.Underline, color: Color.Blue }
])
.width('100%')5. 背景属性
5.1 背景颜色
typescript
Column() {
Text('内容')
}
.width('100%')
.height(200)
.backgroundColor(Color.FromRGB(0xF5, 0xF5, 0xF5))5.2 背景图片
typescript
Column() {
Text('背景图上的内容')
}
.width('100%')
.height(300)
.backgroundImage($r('app.media.banner'))
.backgroundImageSize(ImageSize.Cover)
.backgroundImageRepeat([ImageRepeat.NoRepeat])5.3 渐变背景
typescript
// 线性渐变
Column() {
Text('渐变背景')
}
.width('100%')
.height(200)
.background(
LinearGradient({
startPoint: { x: 0, y: 0 },
endPoint: { x: 1, y: 1 },
colors: [
[Color.FromRGB(0x4A, 0x90, 0xD7), 0.0],
[Color.FromRGB(0x1A, 0xC6, 0xB8), 1.0]
]
})
)6. 边框与圆角
6.1 边框
typescript
Text('有边框')
.border({
width: 1,
color: Color.Gray,
radius: 8 // 边框圆角
})
// 单边边框
Text('上边框')
.borderTop({ width: 1, color: Color.Gray })
.borderBottom({ width: 1, color: Color.Gray })
.borderLeft({ width: 1, color: Color.Gray })
.borderRight({ width: 1, color: Color.Gray })6.2 圆角
typescript
// 统一圆角
Image('avatar')
.width(60)
.height(60)
.borderRadius(30) // 50% 圆角 = 圆形
// 不同方向的圆角
Card() {
Text('卡片内容')
}
.width('100%')
.borderRadius({
topLeft: 12,
topRight: 12,
bottomLeft: 0,
bottomRight: 0
})7. 阴影属性
7.1 通用阴影
typescript
Text('有阴影的文本')
.shadow({
radius: 4,
color: Color.FromRGBA(0, 0, 0, 0.3),
offsetX: 0,
offsetY: 2
})7.2 容器阴影
typescript
Card() {
Text('卡片内容')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.shadow({
radius: 8,
color: Color.FromRGBA(0, 0, 0, 0.15),
offsetX: 0,
offsetY: 4
})8. 可见性与裁剪
8.1 visibility
typescript
Text('可见')
.visibility(Visibility.Visible) // 显示
.visibility(Visibility.Hidden) // 隐藏(占位)
.visibility(Visibility.None) // 隐藏(不占位)8.2 clip
typescript
// 裁剪超出部分
Stack() {
Image('large-image')
.width(200)
.height(200)
}
.width(100)
.height(100)
.borderRadius(8)
.clip({ type: ClipType.Rect }) // 矩形裁剪
// 或
.clip({ type: ClipType.Circle }) // 圆形裁剪9. 事件属性
9.1 点击事件
typescript
Button('点击')
.onClick(() => {
console.log('点击了')
})
// 支持长按
Image('icon')
.onClick(() => console.log('单击'))
.onLongClick(() => console.log('长按'))9.2 拖拽事件
typescript
Image('draggable-icon')
.draggable(true)
.onDragStart(() => {
// 开始拖拽
})
.onDragEnd(() => {
// 拖拽结束
})9.3 触摸事件
typescript
Column() {
Text('触摸我')
}
.onTouch((event: TouchEvent) => {
switch (event.type) {
// 按下、移动、抬起、取消
case TouchType.Down:
console.log('按下')
break
case TouchType.Move:
console.log(`移动: ${event.touches[0].x}, ${event.touches[0].y}`)
break
case TouchType.Up:
console.log('抬起')
break
}
return true // 是否消费事件
})10. 属性链链式调用规则
1. 属性链通过 . 连接
2. 每个属性返回当前组件
3. 可以无限链式调用
4. 最后一条属性的值覆盖前一条
// 正确
Text('Hello')
.fontSize(24)
.fontColor(Color.Red)
.fontWeight(FontWeight.Bold)
// 错误:不能用;结尾打断链
Text('Hello').fontSize(24);
.fontColor(Color.Red) // ❌ 编译错误11. 面试高频考点
Q1: ArkUI 的属性链是什么?
回答:通过 . 连续调用组件的样式方法,每个方法返回组件本身,支持无限链式调用,简洁地设置多个属性。
Q2: visibility 的 Hidden 和 None 区别?
回答:Hidden 隐藏但占位(节点在树中),None 隐藏不占位(节点从树中移除)。频繁切换用 Hidden,不频繁用 None。
Q3: clip 的作用?
回答:裁剪组件的超出部分,支持矩形(Rect)和圆形(Circle)裁剪。常用于头像圆形显示。
🐱 小猫提示:属性部分记住分类:几何/位置/文本/背景/边框/阴影/可见性/事件。面试时按类举例即可。