鴻蒙HarmonyOS中的ArkUI組件庫特性與常用組件實例演示
本文介紹了HarmonyOS的ArkUI組件庫及其核心特性,詳細講解了15個常用組件的使用方法,并通過創(chuàng)建一個電商首頁組件展示了組件的布局和交互效果優(yōu)化,文章還提供了項目運行步驟和效果驗證,幫助讀者掌握組件的開發(fā)和優(yōu)化技巧。
學習目標:
- 理解ArkUI組件的分類與核心特性;
- 掌握15個常用ArkUI組件的用法(布局容器、文本、按鈕、輸入框、列表、網(wǎng)格等);
- 實現(xiàn)一個電商首頁組件(包含輪播圖、分類導航、商品列表、底部導航欄);
- 優(yōu)化組件交互效果(懸停、點擊、滑動動畫)。
學習重點:
- 彈性布局(Flex)與網(wǎng)格布局(Grid)的深度應用;
- 自定義組件與系統(tǒng)組件的結合使用;
- 響應式布局的實現(xiàn)(適配不同設備尺寸)。

一、 ArkUI組件庫概述 ??
1.1 組件分類
HarmonyOS Next的ArkUI組件庫分為基礎組件和高級組件:
| 分類 | 組件示例 |
|---|---|
| 基礎組件 | Text、Image、Button、Input、TextArea、Checkbox、Radio、Slider、Switch |
| 容器組件 | Column、Row、Flex、Grid、GridItem、List、ListItem、Stack |
| 高級組件 | Swiper(輪播圖)、TabContent(標簽頁)、Carousel(卡片輪播)、WaterFlow(瀑布流) |
1.2 核心特性
- 聲明式UI:通過代碼描述UI結構,編譯器自動渲染;
- 數(shù)據(jù)驅動:組件屬性與狀態(tài)數(shù)據(jù)綁定,數(shù)據(jù)變化自動更新UI;
- 響應式布局:自動適配不同設備尺寸;
- 組件復用:支持自定義組件,提高代碼復用率;
- 高性能渲染:采用方舟編譯器編譯,渲染效率比傳統(tǒng)Web開發(fā)高10-20倍。
二、 常用組件實戰(zhàn) ???
2.1 實戰(zhàn)目標
基于第1篇的「MyFirstHarmonyApp」項目架構,創(chuàng)建一個電商首頁組件,包含以下功能:
- 輪播圖(Swiper):展示促銷活動;
- 分類導航(Grid):顯示商品分類;
- 商品列表(List):展示熱門商品;
- 底部導航欄(TabBar):實現(xiàn)頁面切換。
2.2 ?? 項目結構調整
在「entry/src/main/ets」目錄下創(chuàng)建以下文件夾:
components:存放自定義組件;models:存放數(shù)據(jù)模型;utils:存放工具函數(shù)。
2.3 ?? 數(shù)據(jù)模型與工具函數(shù)
1. 數(shù)據(jù)模型
?? entry/src/main/ets/models/HomeModel.ets
// 輪播圖數(shù)據(jù)模型
export interface BannerModel {
id: number;
imageUrl: string;
linkUrl: string;
}
// 分類導航數(shù)據(jù)模型
export interface CategoryModel {
id: number;
name: string;
iconUrl: string;
}
// 商品數(shù)據(jù)模型
export interface GoodsModel {
id: number;
name: string;
imageUrl: string;
price: number;
originalPrice: number;
sales: number;
}
// 底部導航欄數(shù)據(jù)模型
export interface TabBarModel {
id: number;
name: string;
iconUrl: string;
selectedIconUrl: string;
pageUrl: string;
}
2. 工具函數(shù)
?? entry/src/main/ets/utils/ImageUtils.ets
// 圖片加載工具函數(shù)
export function getImageUrl(imagePath: string): string {
return `$r('app.media.${imagePath}')`;
}
3. 模擬數(shù)據(jù)
?? entry/src/main/ets/models/HomeData.ets
import { BannerModel, CategoryModel, GoodsModel, TabBarModel } from './HomeModel';
import { getImageUrl } from '../utils/ImageUtils';
// 輪播圖模擬數(shù)據(jù)
export const bannerData: Array<BannerModel> = [
{ id: 1, imageUrl: getImageUrl('banner1'), linkUrl: 'pages/ProductDetailPage' },
{ id: 2, imageUrl: getImageUrl('banner2'), linkUrl: 'pages/ProductDetailPage' },
{ id: 3, imageUrl: getImageUrl('banner3'), linkUrl: 'pages/ProductDetailPage' }
];
// 分類導航模擬數(shù)據(jù)
export const categoryData: Array<CategoryModel> = [
{ id: 1, name: '手機', iconUrl: getImageUrl('category1') },
{ id: 2, name: '平板', iconUrl: getImageUrl('category2') },
{ id: 3, name: '筆記本', iconUrl: getImageUrl('category3') },
{ id: 4, name: '智能穿戴', iconUrl: getImageUrl('category4') },
{ id: 5, name: '家居', iconUrl: getImageUrl('category5') },
{ id: 6, name: '出行', iconUrl: getImageUrl('category6') }
];
// 商品模擬數(shù)據(jù)
export const goodsData: Array<GoodsModel> = [
{ id: 1, name: '華為Mate 60 Pro', imageUrl: getImageUrl('goods1'), price: 6999, originalPrice: 7999, sales: 12345 },
{ id: 2, name: '華為P60 Pro', imageUrl: getImageUrl('goods2'), price: 5999, originalPrice: 6999, sales: 8765 },
{ id: 3, name: '華為nova 12 Pro', imageUrl: getImageUrl('goods3'), price: 3999, originalPrice: 4999, sales: 6543 },
{ id: 4, name: '華為MateBook X Pro', imageUrl: getImageUrl('goods4'), price: 8999, originalPrice: 9999, sales: 4321 },
{ id: 5, name: '華為Watch GT 4', imageUrl: getImageUrl('goods5'), price: 1499, originalPrice: 1699, sales: 2109 }
];
// 底部導航欄模擬數(shù)據(jù)
export const tabBarData: Array<TabBarModel> = [
{ id: 1, name: '首頁', iconUrl: getImageUrl('tab1'), selectedIconUrl: getImageUrl('tab1_selected'), pageUrl: 'pages/Index' },
{ id: 2, name: '分類', iconUrl: getImageUrl('tab2'), selectedIconUrl: getImageUrl('tab2_selected'), pageUrl: 'pages/CategoryPage' },
{ id: 3, name: '購物車', iconUrl: getImageUrl('tab3'), selectedIconUrl: getImageUrl('tab3_selected'), pageUrl: 'pages/CartPage' },
{ id: 4, name: '我的', iconUrl: getImageUrl('tab4'), selectedIconUrl: getImageUrl('tab4_selected'), pageUrl: 'pages/MyPage' }
];
2.4 ?? 自定義組件實現(xiàn)
1. 輪播圖組件
?? entry/src/main/ets/components/BannerComponent.ets
import { BannerModel } from '../models/HomeModel';
import router from '@ohos.router';
@Component
export struct BannerComponent {
@Prop data: Array<BannerModel> = [];
build() {
Swiper() {
ForEach(this.data, (item: BannerModel) => {
Image(item.imageUrl)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.borderRadius(12)
.onClick(() => {
router.pushUrl({ url: item.linkUrl });
});
}, (item: BannerModel) => item.id.toString());
}
.width('100%')
.height(200)
.autoPlay(true)
.indicator({
style: IndicatorStyle.Number,
isShow: true,
size: 12
})
.loop(true)
.duration(3000);
}
}
2. 分類導航組件
?? entry/src/main/ets/components/CategoryComponent.ets
import { CategoryModel } from '../models/HomeModel';
import router from '@ohos.router';
@Component
export struct CategoryComponent {
@Prop data: Array<CategoryModel> = [];
build() {
Grid() {
ForEach(this.data, (item: CategoryModel) => {
GridItem() {
Column({ space: 8 }) {
Image(item.iconUrl)
.width(50)
.height(50)
.objectFit(ImageFit.Contain);
Text(item.name)
.fontSize(14)
.textColor('#666666');
}
.width('100%')
.height('100%')
.onClick(() => {
router.pushUrl({ url: 'pages/CategoryPage' });
});
}
.width('33.33%')
.height('auto');
}, (item: CategoryModel) => item.id.toString());
}
.width('100%')
.height('auto')
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(20)
.rowsGap(20);
}
}
3. 商品列表組件
?? entry/src/main/ets/components/GoodsListComponent.ets
import { GoodsModel } from '../models/HomeModel';
import router from '@ohos.router';
@Component
export struct GoodsListComponent {
@Prop data: Array<GoodsModel> = [];
build() {
List({ space: 16 }) {
ForEach(this.data, (item: GoodsModel) => {
ListItem() {
GoodsItemComponent({ goods: item });
}
.width('100%')
.height('auto');
}, (item: GoodsModel) => item.id.toString());
}
.width('100%')
.height('auto')
.padding(0, 16, 0, 16);
}
}
@Component
struct GoodsItemComponent {
@Prop goods: GoodsModel;
build() {
Column({ space: 12 }) {
// 商品圖片
Image(this.goods.imageUrl)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.borderRadius(12);
// 商品信息
Column({ space: 8 }) {
Text(this.goods.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.textColor('#000000')
.maxLines(2)
.ellipsis({ overflow: TextOverflow.Ellipsis });
// 價格與銷量
Row({ space: 16 }) {
Column({ space: 4 }) {
Text(`¥${this.goods.price}`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.textColor('#FF0000');
Text(`¥${this.goods.originalPrice}`)
.fontSize(14)
.textColor('#999999')
.decoration({ type: TextDecorationType.LineThrough });
}
.alignItems(HorizontalAlign.Start);
Text(`已售${this.goods.sales}`)
.fontSize(14)
.textColor('#666666');
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween);
}
.width('100%')
.alignItems(HorizontalAlign.Start)
.padding(0, 0, 0, 8);
}
.width('100%')
.height('auto')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.onClick(() => {
router.pushUrl({ url: 'pages/ProductDetailPage' });
});
}
}
4. 底部導航欄組件
?? entry/src/main/ets/components/TabBarComponent.ets
import { TabBarModel } from '../models/HomeModel';
import router from '@ohos.router';
@Component
export struct TabBarComponent {
@Prop data: Array<TabBarModel> = [];
@Prop selectedIndex: number = 0;
build() {
Row({ space: 0 }) {
ForEach(this.data, (item: TabBarModel, index: number) => {
Column({ space: 4 }) {
Image(index === this.selectedIndex ? item.selectedIconUrl : item.iconUrl)
.width(24)
.height(24)
.objectFit(ImageFit.Contain);
Text(item.name)
.fontSize(12)
.textColor(index === this.selectedIndex ? '#007DFF' : '#666666');
}
.width('25%')
.height('100%')
.justifyContent(FlexAlign.Center)
.onClick(() => {
router.pushUrl({ url: item.pageUrl });
});
}, (item: TabBarModel) => item.id.toString());
}
.width('100%')
.height(56)
.backgroundColor('#FFFFFF')
.borderRadius(16, 16, 0, 0)
.padding(0, 8, 0, 8);
}
}
2.5 ?? 首頁頁面實現(xiàn)
?? entry/src/main/ets/pages/Index.ets(替換默認代碼)
import { BannerComponent } from '../components/BannerComponent';
import { CategoryComponent } from '../components/CategoryComponent';
import { GoodsListComponent } from '../components/GoodsListComponent';
import { TabBarComponent } from '../components/TabBarComponent';
import { bannerData, categoryData, goodsData, tabBarData } from '../models/HomeData';
@Entry
@Component
struct Index {
@State selectedIndex: number = 0;
build() {
Column({ space: 0 }) {
// 頁面內容
Scroll() {
Column({ space: 24 }) {
// 輪播圖
BannerComponent({ data: bannerData });
// 分類導航
CategoryComponent({ data: categoryData });
// 熱門商品標題
Text('熱門商品')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.textColor('#000000')
.width('100%')
.padding(0, 0, 0, 16);
// 商品列表
GoodsListComponent({ data: goodsData });
}
.width('100%')
.padding(20);
}
.width('100%')
.height('100%')
.layoutWeight(1);
// 底部導航欄
TabBarComponent({
data: tabBarData,
selectedIndex: this.selectedIndex
});
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5');
}
}
三、 組件交互效果優(yōu)化 ??
3.1 懸停動畫
為商品列表組件添加懸停動畫,提升用戶體驗:
?? entry/src/main/ets/components/GoodsListComponent.ets(修改GoodsItemComponent)
@Component
struct GoodsItemComponent {
@Prop goods: GoodsModel;
@State isHover: boolean = false;
build() {
Column({ space: 12 }) {
// 商品圖片
Image(this.goods.imageUrl)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.borderRadius(12)
.scale({ x: this.isHover ? 1.05 : 1, y: this.isHover ? 1.05 : 1 })
.transition({ duration: 300, curve: Curve.EaseOut });
// 商品信息
// ...
}
.width('100%')
.height('auto')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.onClick(() => {
router.pushUrl({ url: 'pages/ProductDetailPage' });
})
.onHover(() => {
this.isHover = true;
})
.onHoverEnd(() => {
this.isHover = false;
});
}
}
3.2 點擊動畫
為按鈕組件添加點擊動畫,反饋用戶操作:
?? entry/src/main/ets/components/GoodsListComponent.ets(添加立即購買按鈕)
@Component
struct GoodsItemComponent {
@Prop goods: GoodsModel;
@State isHover: boolean = false;
@State isPressed: boolean = false;
build() {
Column({ space: 12 }) {
// 商品圖片
// ...
// 商品信息
Column({ space: 8 }) {
// 商品名稱
// ...
// 價格與銷量
// ...
// 立即購買按鈕
Button('立即購買')
.width('100%')
.height(48)
.backgroundColor('#007DFF')
.onClick(() => {
console.log('點擊了立即購買按鈕');
})
.onPress(() => {
this.isPressed = true;
})
.onPressEnd(() => {
this.isPressed = false;
})
.scale({ x: this.isPressed ? 0.95 : 1, y: this.isPressed ? 0.95 : 1 })
.transition({ duration: 100, curve: Curve.EaseOut });
}
.width('100%')
.alignItems(HorizontalAlign.Start)
.padding(0, 0, 0, 8);
}
.width('100%')
.height('auto')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.onClick(() => {
router.pushUrl({ url: 'pages/ProductDetailPage' });
})
.onHover(() => {
this.isHover = true;
})
.onHoverEnd(() => {
this.isHover = false;
});
}
}
四、 項目運行與效果驗證 ??
4.1 圖片資源準備
在「entry/src/main/resources/base/media」目錄下添加以下圖片資源(圖片格式為.png,尺寸符合要求):
banner1.png、banner2.png、banner3.png(輪播圖);category1.png、category2.png、category3.png、category4.png、category5.png、category6.png(分類導航);goods1.png、goods2.png、goods3.png、goods4.png、goods5.png(商品列表);tab1.png、tab1_selected.png、tab2.png、tab2_selected.png、tab3.png、tab3_selected.png、tab4.png、tab4_selected.png(底部導航欄)。
4.2 ?? 項目運行
① 在DevEco Studio中點擊「Run」按鈕;
② 選擇調試設備,點擊「OK」;
③ 等待編譯安裝完成,應用會自動在設備上啟動。
效果驗證
? 輪播圖:自動輪播促銷活動,點擊可跳轉;
? 分類導航:顯示6個商品分類,點擊可跳轉;
? 商品列表:顯示5個熱門商品,懸停有動畫效果;
? 底部導航欄:實現(xiàn)4個頁面的切換;
? 響應式布局:自動適配不同設備尺寸。
五、 總結與未來學習路徑 ??
5.1 總結
本文完成:
- 對ArkUI組件庫分類與核心特性的理解;
- 15個常用ArkUI組件的實戰(zhàn)應用;
- 一個完整的電商首頁組件的創(chuàng)建;
- 組件交互效果的優(yōu)化(懸停、點擊動畫)。
到此這篇關于鴻蒙HarmonyOS中的ArkUI組件庫特性與常用組件實例演示的文章就介紹到這了,更多相關鴻蒙HarmonyOS的ArkUI組件庫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- 鴻蒙HarmonyOS開發(fā):Navigation路由導航功能和實踐
- 鴻蒙(HarmonyOS)實現(xiàn)隱私政策彈窗效果
- DevEco Studio 2.0開發(fā)鴻蒙HarmonyOS應用初體驗全面測評(推薦)
- 鴻蒙中@State的原理使用詳解(HarmonyOS 5)
- 鴻蒙HarmonyOS App開發(fā)造輪子之自定義圓形圖片組件的實例代碼
- 淺析鴻蒙基礎之Permanent 持久性內存對象(HarmonyOS鴻蒙開發(fā)基礎知識)
- 鴻蒙開發(fā)之處理圖片位圖操作的方法詳解(HarmonyOS鴻蒙開發(fā)基礎知識)
- HarmonyOS開發(fā)基礎知識之Component和ComponentContainer區(qū)別(鴻蒙教程)
- 鴻蒙開發(fā)之Button按鈕類型及如何通過代碼設置(HarmonyOS鴻蒙開發(fā)基礎知識)
- 鴻蒙HarmonyOS 分布式任務調度的實現(xiàn)
- 鴻蒙HarmonyOS剪切板的實現(xiàn)
- 鴻蒙HarmonyOS視頻播放的實現(xiàn)
- HarmonyOS鴻蒙基本控件的實現(xiàn)
- HarmonyOS鴻蒙實現(xiàn)HelloWorld應用開發(fā)E2E體驗
- 鴻蒙游戲開發(fā)實戰(zhàn)從0到1:手把手帶你搭建完整小游戲系統(tǒng)
相關文章
Android Room數(shù)據(jù)庫容易遇到的問題以及解決方法
這篇文章給大家介紹了我們在Android Room數(shù)據(jù)庫容易遇到的坑以及解決方法,文中有詳細的代碼示例供我們參考,具有一定的參考價值,需要的朋友可以參考下2023-09-09
Android獲取當前應用分配的最大內存和目前使用內存的方法
今天小編就為大家分享一篇關于Android獲取當前應用分配的最大內存和目前使用內存的方法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02
Android文本輸入框(EditText)輸入密碼時顯示與隱藏
這篇文章主要介紹了Android文本輸入框(EditText)輸入密碼時顯示與隱藏的方法和示例,需要的朋友可以參考下2014-12-12
Android實現(xiàn)recyclerview城市字母索引列表
大家好,本篇文章主要講的是Android實現(xiàn)recyclerview城市字母索引列表,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01

