Appearance
ArkUI 内置组件
ArkUI 提供了丰富的内置组件,涵盖文本、图片、输入、列表、容器、弹窗等所有常见 UI 元素。
1. 组件分类总览
内置组件
├── 基础组件:Text / Image / Button / Divider
├── 输入组件:TextInput / TextArea / Checkbox / Switch / Slider
├── 容器组件:Column / Row / Stack / Flex / Grid / RelativeContainer
├── 列表组件:List / ListItem / Grid / GridItem / Swiper
├── 滚动组件:Scroll / ListScroller / Refresh
├── 弹窗组件:Dialog / Popup / ActionSheet / CustomDialog
├── 导航组件:Navigation / NavPathStack / NavDestination
└── 媒体组件:Video / Audio / Canvas2. 基础组件
2.1 Text — 文本
typescript
Text('Hello HarmonyOS')
.fontSize(24fp)
.fontColor(Color.Blue)
.fontWeight(FontWeight.Bold)
.fontStyle(FontStyle.Italic)
.textDecorations([TextDecorations.Underline])
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')
.textAlign(TextAlign.Start)
.lineHeight(36fp)
.margin({ top: 10, bottom: 10 })💡 Text 是 ArkUI 中最常用的组件,掌握其全部样式属性。
2.2 Image — 图片
typescript
Image($r('app.media.icon'))
.width(100vp)
.height(100vp)
.borderRadius(12vp) // 圆形图片:borderRadius = width/2
.objectFit(ImageFit.Contain)
.onClick(() => {
console.log('图片点击')
})| objectFit 值 | 效果 |
|---|---|
Fill | 拉伸填充(可能变形) |
Contain | 完整显示(保持比例) |
Cover | 填满容器(可能裁剪) |
ScaleDown | 缩小到Contain |
2.3 Button — 按钮
typescript
Button('提交')
.width('100%')
.height(48vp)
.fontSize(16fp)
.backgroundColor(Color.Blue)
.fontColor(Color.White)
.borderRadius(24vp)
.onClick(() => {
// 点击事件
})
// 按钮类型
Button('默认按钮', { type: ButtonType.Capsule })
Button('次要按钮', { type: ButtonType.Normal })
Button('文字按钮', { type: ButtonType.Text })
Button('描边按钮', { type: ButtonType.Stroked })2.4 Divider — 分隔线
typescript
Divider()
.strokeWidth(1px)
.color(Color.Gray)
.margin({ left: 16, right: 16 })3. 输入组件
3.1 TextInput — 单行输入框
typescript
TextInput({ placeholder: '请输入用户名' })
.width('100%')
.height(48vp)
.fontSize(16fp)
.borderRadius(8vp)
.backgroundColor(Color.White)
.padding(12vp)
.onChange((value: string) => {
// 输入变化回调
this.username = value
})
.type(InputType.Text) // Text/Email/Number/Password
.maxLength(20)| type | 说明 |
|---|---|
InputType.Text | 普通文本 |
InputType.Email | 邮箱键盘 |
InputType.Number | 数字键盘 |
InputType.Password | 密码模式 |
InputType.Phone | 电话键盘 |
3.2 TextArea — 多行文本框
typescript
TextArea({ placeholder: '请输入内容' })
.width('100%')
.height(150vp)
.fontSize(16fp)
.borderRadius(8vp)
.backgroundColor(Color.White)
.padding(12vp)
.onChange((value: string) => {
this.content = value
})
.maxLength(500)3.3 Checkbox — 复选框
typescript
Row() {
Checkbox({ group: 'agree' })
.onChange((isChecked: boolean) => {
this.agreed = isChecked
})
Text('同意用户协议')
.fontSize(14fp)
.margin({ left: 8 })
}3.4 Switch — 开关
typescript
Row() {
Text('开启通知')
.fontSize(16fp)
Switch({ type: SwitchType.CIRCLE })
.selected(this.notificationEnabled)
.onChange((value: boolean) => {
this.notificationEnabled = value
})
}
.alignItems(VerticalAlign.Center)3.5 Slider — 滑块
typescript
Slider({
min: 0,
max: 100,
value: 50,
step: 1
})
.width('80%')
.blockSize(20)
.blockColor(Color.Blue)
.activeColor(Color.Blue)
.normalColor(Color.Gray)
.onChange((value: number) => {
this.volume = value
})4. 列表组件
4.1 List — 列表
typescript
List() {
ListItem() {
Text('Item 1')
}
ListItem() {
Text('Item 2')
}
ListItem() {
Text('Item 3')
}
}
.width('100%')
.height('100%')
.edgePadding({ left: 16, right: 16, top: 10, bottom: 10 })4.2 LazyForEach + List — 长列表(推荐)
typescript
@Entry
@Component
struct Index {
@State items: string[] = []
private myDataSource: MyDataSource = new MyDataSource()
build() {
Column() {
List() {
LazyForEach(this.myDataSource, (item: string) => {
ListItem() {
Text(item)
.fontSize(16fp)
.padding(16vp)
.backgroundColor(Color.White)
.margin({ bottom: 1 })
}
})
}
.width('100%')
.layoutWeight(1)
.edgePadding({ top: 10, bottom: 10 })
}
.width('100%')
.height('100%')
}
}
// IDataSource 实现
class MyDataSource implements IDataSource {
private mData: string[] = []
private listener: DataChangeListener | undefined
refreshData(): void {
// 模拟数据
this.mData = Array.from({ length: 100 }, (_, i) => `Item ${i}`)
if (this.listener) {
this.listener.onDataReload(this)
}
}
getData(index: number): string {
return this.mData[index]
}
getCount(): number {
return this.mData.length
}
registerDataChangeListener(listener: DataChangeListener): void {
this.listener = listener
}
unregisterDataChangeListener(listener: DataChangeListener): void {
this.listener = undefined
}
}4.3 Grid — 网格列表
typescript
Grid() {
ForEach(this.gridItems, (item: any) => {
GridItem() {
Column() {
Image(item.icon)
.width(60vp)
.height(60vp)
Text(item.name)
.fontSize(12fp)
.margin({ top: 8 })
}
}
}, (item: any) => item.id)
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.gap(12)
.width('100%')4.4 Swiper — 轮播图
typescript
Swiper() {
ForEach(this.banners, (banner: Banner) => {
Image(banner.url)
.width('100%')
.height(200vp)
.objectFit(ImageFit.Cover)
}, (banner: Banner) => banner.id)
}
.index(this.currentIndex)
.indicator(true)
.indicatorWidth(60vp)
.indicatorHeight(4vp)
.indicatorBorderRadius(2vp)
.indicatorMargin({ bottom: 10 })
.indicatorStyle(SwiperIndicatorStyle.ROUND)
.interval(3000)
.autoPlay(true)
.loop(true)
.onChange((index: number) => {
this.currentIndex = index
})5. 滚动组件
5.1 Scroll — 滚动容器
typescript
Scroll() {
Column() {
ForEach(this.items, (item: Item) => {
ListItem() {
Text(item.title)
.padding(16vp)
}
})
}
}
.width('100%')
.height('100%')
.scrollBar(BarState.Off) // 隐藏滚动条
.edgePadding({ top: 10, bottom: 10 })
.onScrollFrame((offset: number) => {
// 滚动帧回调
})
.scroller(this.scroller)5.2 Scroll 的属性
| 属性 | 说明 |
|---|---|
scrollBar | 滚动条状态(On/Off/Always) |
edgePadding | 边缘间距 |
vertical | 是否垂直滚动(默认 true) |
showScrollbar | 显示滚动指示器 |
scroller | ScrollScroller 实例(编程式滚动) |
6. 弹窗组件
6.1 Dialog — 系统弹窗
typescript
@Entry
@Component
struct Index {
private controller: DialogController = new DialogController({
autoCancel: true,
alignment: DialogAlignment.Center,
offset: { dx: 0, dy: 0 }
})
build() {
Column() {
Button('打开弹窗')
.onClick(() => {
this.controller.open(
() => {
Text('确认删除吗?')
.fontSize(18fp)
},
[
{ action: '取消', actionChild: () => this.controller.close() },
{ action: '删除', actionChild: () => { /* 删除逻辑 */ ; this.controller.close() } }
],
{ cancel: () => this.controller.close() }
)
})
}
}
}6.2 CustomDialogController — 自定义弹窗
typescript
@CustomDialog
struct ConfirmDialog {
controller: CustomDialogController
title: string = '提示'
content: string = '确定吗?'
build() {
Column() {
Text(this.title)
.fontSize(20fp)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 16 })
Text(this.content)
.fontSize(16fp)
.margin({ bottom: 24 })
Row() {
Button('取消')
.width('48%')
.onClick(() => this.controller.close())
Button('确定')
.width('48%')
.onClick(() => this.controller.close())
}
}
.width('80%')
.padding(24)
}
}
@Entry
@Component
struct Index {
private dialogController = new CustomDialogController({
builder: ConfirmDialog({ title: '提示', content: '确定删除吗?' }),
alignment: DialogAlignment.Center,
customPanelState: CustomPanelState.POPUP
})
build() {
Column() {
Button('打开弹窗')
.onClick(() => this.dialogController.open())
}
}
}7. 导航组件
7.1 Navigation — 页面导航
typescript
@Entry
@Component
struct Index {
private navPathStack: NavPathStack = new NavPathStack()
build() {
Navigation(this.navPathStack) {
NavDestination() {
Text('首页')
.fontSize(32fp)
.fontWeight(FontWeight.Bold)
}
.title('首页')
NavDestination({ type: 'detail' }) {
Text('详情页')
.fontSize(24fp)
}
.title('详情')
}
.width('100%')
.height('100%')
}
}8. 组件属性速查表
| 属性类别 | 常用属性 |
|---|---|
| 几何属性 | width/height/minWidth/maxWidth/minHeight/maxHeight |
| 边距 | margin/padding |
| 位置 | position(left/top/right/bottom) |
| 背景 | backgroundColor/backgroundImage |
| 边框 | border(width/color/radius) |
| 圆角 | borderRadius/clip |
| 阴影 | boxShadow |
| 文字 | fontSize/fontColor/fontWeight/textAlign/maxLines |
| 动画 | animation |
| 可见性 | visibility |
| 点击 | onClick |
| 长按 | onLongClick |
9. 面试高频考点
Q1: 鸿蒙常用的内置组件有哪些?
回答:基础(Text/Image/Button/Divider)、输入(TextInput/TextArea)、列表(List/Grid/Swiper)、滚动(Scroll)、弹窗(Dialog/CustomDialog)、导航(Navigation)等。
Q2: LazyForEach 和 ForEach 的区别?
回答:ForEach 全量渲染,适合少量数据;LazyForEach 按需渲染,配合 IDataSource 使用,长列表必用。
Q3: Swiper 的关键属性?
回答:index、indicator、interval、autoPlay、loop、onChange。用于轮播图的索引、指示器、自动播放和循环。
🐱 小猫提示:内置组件记住核心分组:基础/输入/列表/滚动/弹窗/导航。面试时列举 2-3 个代表组件即可。