本文全面解析ArkUI五大核心组件的花式玩法,助你轻松打造高颜值、强交互的HarmonyOS应用!
涵盖组件全家桶:
✅ 布局容器(Flex/Stack/Grid)
✅ 图片处理(Image/PixelMap/SVG)
✅ 文本魔法(Text/Span)
✅ 输入交互(TextInput/TextArea)
✅ 按钮艺术(Capsule/Circle/Normal)
教程亮点:
🎯 零基础友好:分步图解+口语化讲解
🎨 样式自由定制:边框/阴影/滤镜/动效全解锁
💡 实战场景覆盖:登录页/相册/商品列表/悬浮按钮
🚀 性能优化秘籍:图片缓存/键盘避让/防重复点击
🌼ArkUI布局超全指南 | 看完秒变排版大师!
🌟布局到底是什么?
就像搭积木一样🗿,组件按照特定规则排列组合就形成了页面!在ArkUI中,所有页面都是通过自定义组件+布局魔法搭建的~
开发四步曲🎻:
1️⃣ 画框架:先想好页面长啥样(比如顶部导航+中间内容+底部Tab)
2️⃣ 拆零件:分析要放哪些元素(按钮?图片?列表?)
3️⃣ 选容器:用Column纵向堆叠,Row横向排列,Stack叠叠乐…
4️⃣ 调细节:控制每个元素的位置和大小
🎨布局元素解剖课
%E9%93%BE%E6%8E%A5%E5%8D%A0%E4%BD%8D%E7%AC%A6
🔵 蓝区:组件的”地盘” → 用width/height设定
🟡 黄区:实际可用空间 = 蓝区 – border值
🟢 绿区:内容真实大小(比如文字自动撑开)
⚫ 虚线区:组件+margin的势力范围
对齐小技巧✨:
当内容比黄区小时 → 用align玩对齐魔术(居中/靠左/靠右)
🚀10大布局神器速查表
| 布局方式 | 使用场景 | 举个栗子🌰 |
|---|---|---|
| Row/Column | 需要直线排列时(超过1个元素) | 商品横向排列栏 |
| Stack | 要做叠加效果(比如悬浮按钮) | 图片上叠加收藏图标⭐ |
| Flex | 元素需要自动伸缩比例 | 三栏等分导航 |
| RelativeContainer | 复杂二维布局(拒绝套娃!) | 头像+昵称+简介自由组合 |
| Grid系列 | 需要响应式布局(不同设备自动适配) | 手机/平板不同列数展示 |
| List | 超长滚动列表(聊天记录/商品列表) | 朋友圈动态瀑布流 |
| Swiper | 轮播图/广告横幅 | 电商首页顶部Banner |
| Tabs | 标签页切换(保持导航可见) | 设置页的多个分类 |
🎯定位黑科技
|
1 2 3 4 5 |
// 绝对定位:爸爸的左上角是原点 Component1().position({x: 20, y: 30}) // 相对定位:从自己原来的位置漂移 Component2().offset({x: 5, y: -10}) |
🚨避坑指南:
绝对定位在适配不同屏幕时容易翻车,建议多用相对布局!
🧩子元素控制三大绝招
| 效果 | 属性 | 使用场景 | 代码示例 |
|---|---|---|---|
| 拉伸 | flexGrow/flexShrink | 空间重新分配 | Text('拉伸').flexGrow(1 |
| 缩放 | aspectRatio | 保持宽高比 | Image().aspectRatio(1.5 |
| 隐藏 | displayPriority | 空间不足时智能隐藏 | Button().displayPriority(2 |
💡超实用小贴士
- 百分比布局:
width('50%')超方便,但要注意父容器有没有设置尺寸! - 布局权重:用
layoutWeight让元素自动吃满剩余空间 - 媒体查询:不同设备用不同布局,代码示例:
123456// 手机竖屏显示Column,横屏变Rowif (mediaQuery.matchDevice({orientation: 'portrait'})) {buildColumnLayout()} else {buildRowLayout()}
🎉记住啦! 好的布局 = 选对容器 + 灵活运用定位属性 ~ 现在就去ArkUI里大显身手吧!
🚀ArkUI图片全攻略 | 一文学会花式玩图技巧
🌈Image组件初体验
想让你的APP颜值飙升?Image组件就是你的美图秀秀!支持PNG/JPG/SVG等格式,轻松实现:
✅ 本地图片 ✅ 网络图片 ✅ 矢量图标 ✅ 动态GIF
|
1 2 3 4 |
// 基础用法三连击! Image($r('app.media.logo')) // 资源图片 Image('images/avatar.jpg') // 本地图片 Image('https://example.com/banner.png') // 网络图片 |
📥六种图片加载姿势
| 类型 | 使用场景 | 代码示例 |
|---|---|---|
| 本地图片 | 固定展示的图标/背景 | Image('images/icon.png') |
| 网络图片 | 动态更新的Banner/头像 | Image('https://xxx.jpg') |
| 资源引用 | 跨模块复用图片 | Image($r('app.media.logo')) |
| 媒体库 | 用户相册图片选择 | Image('file://media/Photos/5') |
| Base64 | 小图内嵌(网页常用) | Image('data:image/png;base64,...') |
| PixelMap | 处理解码后的像素数据 | Image(pixelMap对象) |
🛑网络图片必看:
- 需要申请网络权限
ohos.permission.INTERNET - 首次加载会请求网络,后续自动读缓存
- 复杂场景推荐使用ImageKnife库
🎯媒体库图片实战
三步get用户相册美图:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// 1. 引入媒体库模块 import { photoAccessHelper } from '@kit.MediaLibraryKit'; // 2. 创建图片选择器 let picker = new photoAccessHelper.PhotoViewPicker(); picker.select({ MIMEType: 'IMAGE_TYPE', maxSelectNumber: 5 }).then(result => { // 3. 获取选中图片URI this.imgUrls = result.photoUris; }) // 在Grid中展示 Grid() { ForEach(this.imgUrls, (uri) => { GridItem() { Image(uri).width(200).height(200) } }) } |
🔮矢量图魔法时间
SVG图标随心变色!
|
1 2 3 |
Image($r('app.media.cloud')) .width(50) .fillColor(Color.Blue) // 一键换色! |
💡嵌套位图技巧:
|
1 2 3 4 5 6 7 8 9 10 |
// 工程目录结构 ets/ images/ icon.svg sky.png // SVG文件内引用 <svg> <image xlink:href="sky.png"></image> </svg> |
⚙️图片属性调教指南
📐缩放模式大比拼
|
1 2 3 4 5 |
// 六种objectFit效果演示 Image($r('app.media.pic')) .objectFit(ImageFit.Contain) // 等比例完整显示 .objectFit(ImageFit.Cover) // 填满容器并裁剪 .objectFit(ImageFit.Fill) // 拉伸变形填满 |
🖼️重复平铺特效
|
1 2 3 4 |
// 四种重复模式 Image($r('app.media.pattern')) .objectRepeat(ImageRepeat.XY) // 双向平铺 .objectRepeat(ImageRepeat.X) // 横向平铺 |
🎨滤镜调色板
|
1 2 3 4 5 6 7 8 |
// 添加复古滤镜 Image($r('app.media.photo')) .colorFilter([ 0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0 ]) |
⚡性能优化秘籍
- 解码尺寸控制 – 降低分辨率
12Image($r('app.media.high_res')).sourceSize({ width: 100, height: 100 }) // 强制解码为100x100
- 插值抗锯齿 – 放大不模糊
12Image($r('app.media.low_res')).interpolation(ImageInterpolation.High) // 高质量插值
- 同步加载 – 防闪烁(慎用!)
12Image($r('app.media.banner')).syncLoad(true) // 可能阻塞UI!
🔔事件监听小助手
|
1 2 3 4 5 6 7 |
Image($r('app.media.dynamic')) .onComplete((msg) => { // 加载成功回调 console.log(`图片尺寸:${msg.width}x${msg.height}`) }) .onError(() => { // 加载失败处理 console.log('图片加载失败啦!') }) |
🎉终极Tips:
- 网络图片记得处理加载状态(占位图+错误提示)
- SVG图标优先选择,适配不同分辨率屏幕
- 大图建议使用缩略图+点击查看原图方案
- 定期清理图片缓存防止OOM
现在就去用Image组件打造你的视觉盛宴吧!🚀
📚ArkUI文本全解 | Text和Span的魔法手册
🎨文本创建三连击
方式一:直接字符串
|
1 |
Text('我是人见人爱的文本宝宝~') |
方式二:资源引用
|
1 2 3 4 |
// 在string.json定义资源 Text($r('app.string.welcome')) .fontSize(30) .border({ width: 1 }) |
彩蛋玩法:
✅ 支持多语言资源
✅ 自动适配系统字体大小
✅ 跨模块复用文本资源
👯Text和Span的共舞
| 组件 | 特性 | 使用场景 |
|---|---|---|
| Text | 独立显示文本 | 普通段落、标题 |
| Span | 必须嵌套在Text中使用 | 行内多样式文本组合 |
CP组合技演示:
|
1 2 3 4 5 6 7 8 9 10 11 |
Text('主文本') { Span('红色删除线').decoration({ type: TextDecorationType.LineThrough, color: Color.Red }) Span('蓝色下划线').decoration({ type: TextDecorationType.Underline, color: Color.Blue }) } .borderWidth(1) |
✨文本样式美容院
📐对齐与溢出
|
1 2 3 4 5 6 7 8 9 |
// 三种对齐方式 Text('左对齐').textAlign(TextAlign.Start) Text('居中').textAlign(TextAlign.Center) Text('右对齐').textAlign(TextAlign.End) // 超长文本处理 Text('很长很长的内容...') .maxLines(1) .textOverflow({overflow: TextOverflow.Ellipsis}) // 显示... |
🎭文字变形术
|
1 2 3 4 |
Text('Hello World') .textCase(TextCase.UpperCase) // 全大写 .letterSpacing(5) // 字间距 .baselineOffset(10) // 基线偏移 |
🌈动态字号
|
1 2 3 4 5 6 |
// 自适应字号(根据容器大小) Text('智能缩放文字') .maxFontSize(30) .minFontSize(12) .height(50) .width(200) |
⚡交互与事件
🖱️点击响应
|
1 2 3 4 5 6 7 8 9 10 11 |
Text('点我有惊喜!') .onClick(() => { console.log('文本被点击啦!') }) Text() { Span('可点击Span') .onClick(() => { console.log('Span被戳中~') }) } |
⚠️注意:
- Span仅支持点击事件
- Text支持所有通用事件(onTouch/onLongPress等)
🎩高级特效秀
📜滚动字幕
|
1 2 3 |
Text('紧急通知:ArkUI 3.0发布啦!') .textOverflow({overflow: TextOverflow.Marquee}) .maxLines(1) |
📋复制粘贴
|
1 2 |
Text("长按复制我") .copyOption(CopyOptions.InApp) // 允许应用内复制 |
🖌️文字阴影
|
1 2 3 4 5 6 7 |
Text('立体文字') .textShadow({ radius: 5, color: Color.Grey, offsetX: 2, offsetY: 2 }) |
💡最佳实践Tips
- 性能优化:
- 避免在滚动视图中使用复杂Span嵌套
- 长文本优先使用Ellipsis代替Marquee
- 国际化:
12// 使用资源引用适配多语言Text($r('app.string.greeting'))
2.无障碍:
12Text('重要提示').accessibilityDescription('这是关于系统更新的重要通知')
3.样式复用:
1234567// 使用@Styles定义通用样式@Styles function boldRed() {.fontColor(Color.Red).fontWeight(FontWeight.Bold)}Text('重点内容').boldRed()
🎉现在就去用Text和Span打造你的文字艺术馆吧!
🚀ArkUI输入框终极指南 | TextInput & TextArea全掌握
📱输入框双雄登场
TextInput – 单行输入小王子
TextArea – 多行文本大管家
|
1 2 3 4 5 6 |
// 基础创建姿势 TextInput() // 单行输入 TextArea() // 多行输入(自动换行) // 带预设文本 TextArea({ text: "我是超长文本..." }).width(300) |
🔧七大输入类型任你选
| 类型 | 场景 | 代码示例 |
|---|---|---|
| Normal | 普通文本输入 | .type(InputType.Normal) |
| Password | 密码输入(圆点隐藏) | .type(InputType.Password) |
| 邮箱格式校验 | .type(InputType.Email) |
|
| Number | 纯数字键盘 | .type(InputType.Number) |
| PhoneNumber | 电话号码输入 | .type(InputType.PhoneNumber) |
| URL | 网址输入(自动补全) | .type(InputType.URL) |
| NUMBER_DECIMAL | 带小数点的数字 | .type(InputType.NUMBER_DECIMAL) |
🎨个性化装扮指南
📝基础装扮三件套
|
1 2 3 4 5 6 |
TextInput({ placeholder: '请输入用户名', // 提示文字 text: '默认内容' // 预设文本 }) .backgroundColor(Color.Pink) // 粉嫩背景 .fontColor(Color.Black) // 文字颜色 |
🖌️高级样式魔法
✅ 边框定制
✅ 圆角效果
✅ 字体大小调整
✅ 输入框尺寸控制
|
1 2 3 4 5 6 7 8 |
TextInput() .width('90%') .height(50) .border({ width: 2, color: Color.Blue, radius: 10 }) |
⚡事件监听大师课
|
1 2 3 4 5 6 7 8 9 10 11 12 |
TextInput() // 内容变化实时监听 .onChange((value: string) => { console.log(`输入内容:${value}`); }) // 聚焦/失焦监听 .onFocus(() => console.log('获得焦点')) .onBlur(() => console.log('失去焦点')) // 回车键响应 .onSubmit((keyType) => { console.log(`回车类型:${keyType}`); }) |
📱登录页面实战
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Entry @Component struct LoginPage { build() { Column() { TextInput({ placeholder: '账号' }) .margin(20) .type(InputType.USER_NAME) TextInput({ placeholder: '密码' }) .margin(20) .type(InputType.PASSWORD) Button('登录', { type: ButtonType.Capsule }) .width(200) .margin(20) } .padding(20) } } |
🛡️键盘避让黑科技
为什么需要?
手机键盘弹出时可能遮挡输入框!
解决方案:
用Scroll/List/Grid包裹输入容器
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Entry @Component struct ChatPage { build() { Scroll() { // 关键包裹层! Column() { ForEach(消息列表, (消息) => { TextArea({ text: 消息内容 }) .margin(10) }) } } .height('100%') } } |
💡超实用技巧合集
智能字号调整
|
1 2 3 |
TextInput() .maxFontSize(20) .minFontSize(12) // 根据容器自动缩放 |
禁止复制粘贴
|
1 2 |
TextInput() .copyOption(CopyOptions.None) |
输入长度限制
|
1 2 |
TextInput() .maxLength(10) // 最多输入10字符 |
光标控制
|
1 2 3 4 5 |
const controller = new TextInputController() TextInput({ controller }) .onClick(() => { controller.caretPosition(5) // 光标定位到第5位 }) |
🚨避坑指南
⚠️ 多行输入避免使用height固定高度 → 用maxLines控制
⚠️ 密码输入记得搭配.type(InputType.Password)
⚠️ 表单提交前务必做输入校验
🎉现在就去打造你的智能输入界面吧! 记得多用Scroll解决键盘遮挡问题哦~ 🚀
🚀ArkUI按钮全攻略 | 玩转交互设计就靠它!
🛠️按钮创建双模式
模式一:文字按钮
|
1 2 3 4 5 6 7 8 9 |
// 基础文字按钮 Button('确认', { type: ButtonType.Normal, stateEffect: true // 开启点击动效 }) .borderRadius(8) .backgroundColor(0x317aff) .width(90) .height(40) |
模式二:图文混合按钮
|
1 2 3 4 5 6 7 8 9 10 |
// 图标+文字组合按钮 Button({ type: ButtonType.Capsule }) { Row() { Image($r('app.media.ic_star')) .width(20).height(20).margin({ left: 10 }) Text('收藏').fontSize(12).margin({ left: 5, right: 10 }) }.alignItems(VerticalAlign.Center) } .backgroundColor(Color.Blue) .width(120) |
🎨按钮类型三剑客
| 类型 | 特性 | 代码示例 |
|---|---|---|
| 胶囊按钮 | 圆角=高度/2(不可修改) | ButtonType.Capsule |
| 圆形按钮 | 正圆形状(不可修改圆角) | ButtonType.Circle |
| 普通按钮 | 自定义圆角(默认直角) | ButtonType.Normal |
示例对比:
|
1 2 3 4 5 6 7 8 9 10 11 |
// 胶囊按钮(自动圆角) Button('删除', { type: ButtonType.Capsule }) .width(100).height(40) // 圆形按钮(固定圆形) Button('+', { type: ButtonType.Circle }) .width(60).height(60) // 普通按钮(自定义圆角) Button('分享', { type: ButtonType.Normal }) .borderRadius(20) |
✨样式美容院
🎩百变造型
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// 渐变背景按钮 Button('VIP专属') .linearGradient({ angle: 90, colors: [[0xffd700, 0], [0xff4500, 1]] }) // 边框发光按钮 Button('新消息') .border({ width: 2, color: Color.White, style: BorderStyle.Dotted }) .shadow({ radius: 10, color: Color.Blue }) |
🖼️图标功能按钮
|
1 2 3 4 5 6 7 |
// 删除按钮 Button({ type: ButtonType.Circle }) { Image($r('app.media.ic_delete')) .width(30).height(30) } .width(50).height(50) .backgroundColor(Color.Red) |
⚡点击魔法
基础点击事件
|
1 2 3 4 5 |
Button('立即购买') .onClick(() => { console.log('商品加入购物车') // 这里调用支付接口 }) |
防重复点击
|
1 2 3 4 5 6 7 8 9 |
let isProcessing = false Button('提交订单') .onClick(() => { if (isProcessing) return isProcessing = true // 执行提交逻辑 setTimeout(() => { isProcessing = false }, 1000) }) |
🚀实战演练室
📱页面导航按钮
|
1 2 3 4 5 |
// 跳转到设置页 Button('设置') .onClick(() => { router.pushUrl({ url: 'pages/Settings' }) }) |
🔐登录注册按钮
|
1 2 3 4 5 6 7 8 9 |
Column() { TextInput({ placeholder: '手机号' }) TextInput({ placeholder: '密码' }).type(InputType.Password) Button('注册', { type: ButtonType.Capsule }) .width('80%') .onClick(() => { // 调用注册API }) } |
🎯悬浮动作按钮
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Stack() { List() { /* 长列表内容 */ } Button({ type: ButtonType.Circle }) { Image($r('app.media.ic_add')) .width(40).height(40) } .width(60).height(60) .position({ x: '85%', y: '80%' }) .shadow({ radius: 10 }) .onClick(() => { // 弹出新建内容浮层 }) } |
💡超实用技巧
禁用状态
|
1 2 3 |
Button('已售罄') .enabled(false) // 禁用点击 .opacity(0.6) // 透明度变化 |
加载中状态
|
1 2 3 4 |
Button({ type: ButtonType.Normal }) { LoadingProgress().width(20).height(20) Text('加载中...').margin({ left: 8 }) } |
长按菜单
|
1 2 3 4 |
Button('长按复制') .onLongPress(() => { clipboard.copy('复制的内容') }) |
按键反馈
|
1 2 3 4 5 6 |
Button('震动反馈') .onTouch((event) => { if (event.type === TouchType.Down) { vibrator.vibrate(50) // 按下时震动50ms } }) |
🚨避坑指南
⚠️ 胶囊按钮不要设置borderRadius(无效)
⚠️ 图文按钮确保子组件不超过一个
⚠️ 悬浮按钮需用Stack布局防止滚动遮挡
⚠️ 提交按钮务必做防重复点击处理
🎉现在就去用Button点亮你的交互设计吧! 记得多用不同样式区分主要/次要操作哦~ 🚀