| ---------------------------------------------------------------------------------------- |# 概述
OpenHarmony ArkUI框架提供了豐富的動畫組件和接口,開發者可以根據實際場景和開發需求,選用豐富的動畫組件和接口來實現不同的動畫效果。
本Codelab中,我們會構建一個簡易的購物應用。應用包含兩級頁面,分別是主頁(“商品瀏覽”頁簽、“購物車”頁簽、“我的”頁簽)和商品詳情頁面。效果如下圖所示:
代碼結構解讀
本篇Codelab只對核心代碼進行講解,首先來介紹下整個工程的代碼結構:
- model:存放封裝好的數據實體。
- ArsData:我的頁簽相關參數實體。
- GoodsData:商品列表頁商品實體。
- GoodsDataModels:各種實體的具體數據以及獲取數據的方法。
- Menu:我的頁簽菜單實體。
- pages:存放頁面。
- resources :存放工程使用到的資源文件。
- resources/base/media:存放工程中使用的圖片資源。
- config.json:配置文件。
- 鴻蒙開發指導文檔:[
gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
搭建OpenHarmony環境
完成本篇Codelab我們首先要完成開發環境的搭建,本示例以Hi3516DV300開發板為例,參照以下步驟進行:
- [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)
以3.0版本為例: - 搭建燒錄環境
- [完成DevEco Device Tool的安裝]
- [完成Hi3516開發板的燒錄]
- 搭建開發環境
- 開始前請參考[工具準備],完成DevEco Studio的安裝和開發環境配置。
- 開發環境配置完成后,請參考[使用工程向導]創建工程(模板選擇“Empty Ability”),選擇JS或者eTS語言開發。
- 工程創建完成后,選擇使用[真機進行調測]。
HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿
構建商品列表頁簽
在本節中,我們將完成商品列表頁簽的設計,效果圖如下:
從效果圖可以看出,商品列表頁簽主要由三個部分組成:
- 頂部的Tabs組件。
- 中間TabContent組件內包含List組件。其中List組件的item是一個水平布局,由一個垂直布局和一個Image組件組成;item中的垂直布局由3個Text組件組成。
- 底部的導航頁簽navigation組件。
實現步驟如下:
- 在pages目錄下面新建一個ETS Page,命名為HomePage.ets,在config.json文件的pages屬性中會自動添加“pages/HomePage”頁面路由。
說明:
- 頁面文件名不能使用組件名稱,比如:Text.ets、Button.ets等。
- 每個頁面文件中必須包含入口組件。
新建與pages文件夾同級的model文件夾,并在model目錄下新建ArsData.ets、GoodsData.ets、Menu.ets和GoodsDataModels.ets文件,其中ArsData.ets、GoodsData.ets、Menu.ets是數據實體類,GoodsDataModels.ets是存放這三種實體數據集合,并定義了獲取各種數據集合的方法。數據實體包含實體的屬性和構造方法,可通過new ArsData(string,string) 來獲取ArsData對象,ArsData.ets內容如下:
let NextId = 0; export class ArsData { id: string; title: string; content: string; constructor(title: string, content: string) { this.id = `${NextId++}`; this.title = title; this.content = content; } }
GoodsData.ets代碼如下:
let NextId = 0; export class GoodsData { id: string; title: string; content: string; price: number; imgSrc: Resource; constructor(title: string, content: string, price: number, imgSrc: Resource) { this.id = `${NextId++}`; this.title = title; this.content = content; this.price = price; this.imgSrc = imgSrc; } }
一個文件中可以包含多個class ,Menu.ets中就包含了Menu類和ImageItem類,Menu.ets代碼如下
let NextId = 0; export class Menu { id: string; title: string; num: number; constructor(title: string, num: number) { this.id = `${NextId++}`; this.title = title; this.num = num; } } export class ImageItem { id: string; title: string; imageSrc: Resource; constructor(title: string, imageSrc: Resource) { this.id = `${NextId++}`; this.title = title; this.imageSrc = imageSrc; } }
GoodsDataModels.ets代碼如下:
import {GoodsData} from './GoodsData' import {Menu, ImageItem} from './Menu' import {ArsData} from './ArsData' //獲取商品列表數據 export function initializeOnStartup(): Array< GoodsData > { let GoodsDataArray: Array< GoodsData > = [] GoodsComposition.forEach(item = > { console.log(item.title); GoodsDataArray.push(new GoodsData(item.title, item.content, item.price, item.imgSrc)); }) return GoodsDataArray; } //獲取底部默認圖片列表數據 export function getIconPath(): Array< string > { let IconPath: Array< string > = ['nav/icon-buy.png','nav/icon-shopping-cart.png','nav/icon-my.png'] return IconPath; } //獲取選中后圖片列表數據 export function getIconPathSelect(): Array< string > { let IconPathSelect: Array< string > = ['nav/icon-home.png','nav/icon-shopping-cart-select.png','nav/icon-my-select.png'] return IconPathSelect; } //獲取商品詳情頁圖片詳情列表 export function getDetailImages(): Array< string > { let detailImages: Array< string > = ['computer/computer1.png','computer/computer2.png','computer/computer3.png','computer/computer4.png','computer/computer5.png','computer/computer6.png'] return detailImages; } //獲取菜單數據列表 export function getMenu(): Array< Menu > { let MenuArray: Array< Menu > = [] MyMenu.forEach(item = > { MenuArray.push(new Menu(item.title,item.num)); }) return MenuArray; } //獲取MyTrans數據列表 export function getTrans(): Array< ImageItem > { let ImageItemArray: Array< ImageItem > = [] MyTrans.forEach(item = > { ImageItemArray.push(new ImageItem(item.title,item.imageSrc)); }) return ImageItemArray; } //獲取More數據列表 export function getMore(): Array< ImageItem > { let ImageItemArray: Array< ImageItem > = [] MyMore.forEach(item = > { ImageItemArray.push(new ImageItem(item.title,item.imageSrc)); }) return ImageItemArray; } //獲取參數列表 export function getArs(): Array< ArsData > { let ArsItemArray: Array< ArsData > = [] ArsList.forEach(item = > { ArsItemArray.push(new ArsData(item.title,item.content)); }) return ArsItemArray; } //數據集合部分 ...
在HomePage.ets文件中創建商品列表頁簽相關的組件,其中GoodsHome效果圖如下:
代碼如下:@Component @Component struct GoodsHome { private goodsItems: GoodsData[] build() { Column() { Tabs() { TabContent() { GoodsList({ goodsItems: this.goodsItems }); } .tabBar("Top Sellers") .backgroundColor(Color.White) TabContent() { GoodsList({ goodsItems: this.goodsItems }); } .tabBar("Recommended") .backgroundColor(Color.White) TabContent() { GoodsList({ goodsItems: this.goodsItems }); } .tabBar("Lifestyle") .backgroundColor(Color.White) TabContent() { GoodsList({ goodsItems: this.goodsItems }); } .tabBar("Deals") .backgroundColor(Color.White) } .barWidth(540) .barHeight(50) .scrollable(true) .barMode(BarMode.Scrollable) .backgroundColor('#007DFF') .height('100%') } .alignItems(HorizontalAlign.Start) } }
在GoodsHome中使用Tabs組件,在Tabs組件中設置4個TabContent,給每個TabContent設置tabBar屬性,并設置TabContent容器中的內容GoodsList組件,GoodsList組件效果圖如下:
代碼如下:
@Component struct GoodsList { private goodsItems: GoodsData[] build() { Column() { List() { ForEach(this.goodsItems, item = > { ListItem() { GoodsListItem({ goodsItem: item }) } }, item = > item.id.toString()) } .height('100%') .width('100%') .align(Alignment.Top) .margin({top: 5}) } } }
在GoodsList組件中遍歷商品數據集合,ListItem組件中設置組件內容,并使用Navigator組件給每個Item設置頂級跳轉路由,GoodsListItem組件效果圖如下:
代碼如下:
@Component struct GoodsListItem { private goodsItem: GoodsData build() { Navigator({ target: 'pages/ShoppingDetail' }) { Row() { Column() { Text(this.goodsItem.title) .fontSize(18) Text(this.goodsItem.content) .fontSize(14) Text('¥' + this.goodsItem.price) .fontSize(18) .fontColor(Color.Red) } .height(130) .width('60%') .margin({ left: 20 }) .alignItems(HorizontalAlign.Start) Image(this.goodsItem.imgSrc) .objectFit(ImageFit.ScaleDown) .height(130) .width('30%') .renderMode(ImageRenderMode.Original) .margin({ right: 10, left: 10 }) } .backgroundColor(Color.White) } .params({ goodsData: this.goodsItem }) .margin({ right: 5 }) } }
在HomePage.ets中創建文件入口組件(Index)以及底部頁簽導航組件(Navigation),導入需要使用到的數據實體類以及需要使用的方法和組件,每個page文件都必須包含一個入口組件,使用@Entry修飾,HomePage文件中的入口組件(Index)代碼如下:
import { GoodsData, IconImage } from '../model/GoodsData' import { initializeOnStartup, getIconPath, getIconPathSelect } from '../model/GoodsDataModels' import { ShoppingCart } from './ShoppingCartPage.ets' import { MyInfo } from './MyPage.ets' import router from '@system.router'; @Entry @Component struct Index { @Provide currentPage: number = 1 private goodsItems: GoodsData[] = initializeOnStartup() @State Build: Array< Object > = [ { icon: $r('app.media.icon_home'), icon_after: $r('app.media.icon_buy1'), text: '首頁', num: 0 }, { icon: $r('app.media.icon_shopping_cart'), icon_after: $r('app.media.icon_shopping_cart_select'), text: '購物車', num: 1 }, { icon: $r('app.media.icon_my'), icon_after: $r('app.media.icon_my_select'), text: '我的', num: 2 } ] @Builder NavigationToolbar() { Flex({direction:FlexDirection.Row,wrap:FlexWrap.NoWrap,justifyContent:FlexAlign.SpaceAround}) { ForEach(this.Build, item = > { Column() { Image(this.currentPage == item.num ? item.icon_after : item.icon) .width(25) .height(25) Text(item.text) .fontColor(this.currentPage == item.num ? "#ff7500" : "#000000") } .onClick(() = > { this.currentPage = item.num }) }) } } build() { Column() { Navigation() { Flex() { if (this.currentPage == 0) { GoodsHome({ goodsItems: this.goodsItems }) } if (this.currentPage == 1) { ShoppingCart() //購物車列表 } if (this.currentPage == 2) { MyInfo() //我的 } } .width('100%') .height('100%') } .toolBar(this.NavigationToolbar) .title("購物車") .hideTitleBar(this.currentPage == 1 ? false : true) .hideBackButton(true) } } }
從入口組件的代碼中可以看出,我們定義了一個全局變量currentPage ,當currentPage發生變化的時候,會顯示不同的頁簽。在入口組件中,通initializeOnStartup獲取商品列表數據(goodsItems)并傳入GoodsHome組件中。效果圖如下:
構建購物車頁簽
從上面效果圖可以看出,主界面購物車頁簽主要由下面三部分組成:
- 頂部的title,由Navigation組件title屬性設置。
- 中間的List組件,其中List組件的item是一個水平的布局內包含一個toggle組件,一個Image組件和一個垂直布局,其item中的垂直布局是由2個Text組件組成。
- 底部一個水平布局包含兩個Text組件。
在本任務中我們主要是構建一個購物車頁簽,給商品列表的每個商品設置一個單選框,可以選中與取消選中,底部Total值也會隨之增加或減少,點擊Check Out時會觸發彈窗。下面我們來完成ShoppingCart頁簽。
在pages目錄下面新建一個ETS Page ,命名為ShoppingCart.ets,config.json文件pages屬性中也會自動添加“pages/ShoppingCart”頁面路由。
在ShoppingCartPage.ets文件中添加入口組件(ShoppingCart),并導入需要使用到的數據實體類、方法和組件。ShoppingCart組件代碼如下:
import {GoodsData} from '../model/GoodsData' import {initializeOnStartup} from '../model/GoodsDataModels' import prompt from '@system.prompt'; @Entry @Component export struct ShoppingCart { @Provide totalPrice: number = 0 private goodsItems: GoodsData[] = initializeOnStartup() build() { Column() { ShopCartList({ goodsItems: this.goodsItems }); ShopCartBottom() } .height('100%') .width('100%') .alignItems(HorizontalAlign.Start) } }
新建ShopCartList組件用于存放購物車商品列表,ShopCartList組件效果圖如下:
代碼如下:@Component struct ShopCartList { private goodsItems: GoodsData[] build() { Column() { List() { ForEach(this.goodsItems, item = > { ListItem() { ShopCartListItem({ goodsItem: item }) } }, item = > item.id.toString()) } .height('100%') .width('100%') .align(Alignment.Top) .margin({ top: 5 }) } .height('90%') } }
在ShopCartListItem中使用Toggle的單選框類型來實現每個item的選擇和取消選擇,在Toggle的onChage事件中來改變totalPrice的數值。ShopCartListItem組件效果圖如下:
代碼如下:
@Component struct ShopCartListItem { @Consume totalPrice: number private goodsItem: GoodsData build() { Row() { Toggle({ type: ToggleType.Checkbox }) .width(13) .height(13) .onChange((isOn: boolean) = > { if (isOn) { this.totalPrice += parseInt(this.goodsItem.price + '', 0) } else { this.totalPrice -= parseInt(this.goodsItem.price + '', 0) } }) Image(this.goodsItem.imgSrc) .objectFit(ImageFit.ScaleDown) .height(130) .width(100) .renderMode(ImageRenderMode.Original) Column() { Text(this.goodsItem.title) .fontSize(18) Text('¥' + this.goodsItem.price) .fontSize(18) .fontColor(Color.Red) } .margin({left:40}) } .height(100) .width('100%') .margin({ left: 20 }) .alignItems(VerticalAlign.Center) .backgroundColor(Color.White) } }
新建ShopCartBottom組件,ShopCartBottom組件效果圖如下:
代碼如下:@Component struct ShopCartBottom { @Consume totalPrice: number build() { Row() { Text('Total: ¥' + this.totalPrice) .fontColor(Color.Red) .fontSize(18) .margin({ left: 20 }) .width(150) Text('Check Out') .fontColor(Color.Black) .fontSize(18) .margin({ right: 20, left: 180 }) .onClick(() = > { prompt.showToast({ message: 'Checking Out', duration: 10, bottom: 100 }) }) } .height(30) .width('100%') .backgroundColor('#FF7FFFD4') .alignItems(VerticalAlign.Bottom) } }
構建我的頁簽
從上面效果圖可以看出,主界面我的頁簽主要由下面四部分組成:
- 頂部的水平布局。
- 頂部下面的文本加數字的水平List。
- My Transactio模塊,圖片加文本的水平List。
- More模塊,圖片加文本的Grid。
在本任務中,我們構建主頁我的頁簽,主要可以劃分成下面幾步:
在pages目錄下面新建一個ETS Page 命名為MyPage.ets,在config.json文件pages屬性中也會自動添加“pages/MyPage”頁面路由。
在MyPage.ets文件中添加入口組件(MyInfo),組件內容如下:
import {getMenu,getTrans,getMore} from '../model/GoodsDataModels' import {Menu, ImageItem} from '../model/Menu' @Entry @Component export struct MyInfo { build() { Column() { Row() { Image($r('app.media.icon_user')) .objectFit(ImageFit.Contain) .height(50) .width(50) .margin({left:10}) .renderMode(ImageRenderMode.Original) Column() { Text('John Doe') .fontSize(15) Text('Member Name : John Doe >') .fontSize(15) } .height(60) .margin({ left: 20, top: 10 }) .alignItems(HorizontalAlign.Start) } TopList() MyTransList() MoreGrid() } .alignItems(HorizontalAlign.Start) .width('100%') .height('100%') .flexGrow(1) } }
入口組件中還包含TopList,MyTransList和MoreGrid三個子組件。
在MyPage.ets文件中新建TopList組件,效果圖如下:
代碼如下:@Component struct TopList { private menus: Menu1[] = getMenu() build() { Row() { List() { ForEach(this.menus, item = > { ListItem() { MenuItem({ menu: item }) } }, item = > item.id.toString()) } .height('100%') .width('100%') .margin({ top: 5,left: 10}) .edgeEffect(EdgeEffect.None) .listDirection(Axis.Horizontal) } .width('100%') .height(50) } }
getMenu()方法在上文中已有定義,是獲取菜單列表的方法,TopList的子組件MenuItem內容如下:
@Component struct MenuItem { private menu: Menu1 build() { Column() { Text(this.menu.title) .fontSize(15) Text(this.menu.num + '') .fontSize(13) } .height(50) .width(100) .margin({ left: 8, right: 8 }) .alignItems(HorizontalAlign.Start) .backgroundColor(Color.White) } }
在MyPage.ets文件中新建MyTransList組件和MoreGrid組件,MyTransList組件效果如如下:
代碼如下:@Component struct MyTransList { private imageItems: ImageItem[] = getTrans() build() { Column() { Text('My Transaction') .fontSize(20) .margin({ left: 10 }) .width('100%') .height(30) Row() { List() { ForEach(this.imageItems, item = > { ListItem() { DataItem({ imageItem: item }) } }, item = > item.id.toString()) } .height(70) .width('100%') .edgeEffect(EdgeEffect.None) .margin({ top: 5 }) .padding({ left: 16, right: 16 }) .listDirection(Axis.Horizontal) } } .height(120) } }
MoreGrid組件效果圖如下:
代碼如下:
@Component struct MoreGrid { private gridRowTemplate: string = '' private imageItems: ImageItem[] = getMore() private heightValue: number aboutToAppear() { var rows = Math.round(this.imageItems.length / 3); this.gridRowTemplate = '1fr '.repeat(rows); this.heightValue = rows * 75; } build() { Column() { Text('More') .fontSize(20) .margin({ left: 10 }) .width('100%') .height(30) Scroll() { Grid() { ForEach(this.imageItems, (item: ImageItem) = > { GridItem() { DataItem({ imageItem: item }) } }, (item: ImageItem) = > item.id.toString()) } .rowsTemplate(this.gridRowTemplate) .columnsTemplate('1fr 1fr 1fr') .columnsGap(8) .rowsGap(8) .height(this.heightValue) } .padding({ left: 16, right: 16 }) } .height(400) } }
在MyTransList和MoreGrid組件中都包含子組件DataItem,為避免的重復代碼,可以把多次要用到的結構體組件化,這里的結構體就是圖片加上文本的上下結構體,DataItem組件內容如下:
@Component struct DataItem { private imageItem: ImageItem build() { Column() { Image(this.imageItem.imageSrc) .objectFit(ImageFit.Contain) .height(50) .width(50) .renderMode(ImageRenderMode.Original) Text(this.imageItem.title) .fontSize(15) } .height(70) .width(150) .margin({ left: 10, right: 10 }) .backgroundColor(Color.White) } }
構建商品詳情頁面
從上面效果圖可以看出,商品詳情頁面主要由下面五部分組成:
- 頂部的返回欄。
- Swiper組件。
- 中間多個Text組件組成的布局。
- 參數列表。
- 底部的Buy。
在本任務中,把上面每一部分都封裝成一個組件,然后再放到入口組件內,當點擊頂部返回圖標時返回到主頁面的商品列表頁簽,點擊底部Buy時,會觸發進度條彈窗
在pages目錄下面新建一個ETS Page, 命名為ShoppingDetail.ets,config.json文件pages屬性中也會自動添加“pages/ShoppingDetail”頁面路由。
在ShoppingDetail.ets文件中創建入口組件,組件內容如下:
@Entry @Component struct ShoppingDetail { private arsItems: ArsData[] = getArs() build() { Column() { DetailTop() Scroll() { Column() { SwiperTop() DetailText() DetailArsList({ arsItems: this.arsItems }) Image($r('app.media.computer1')) .height(220) .width('100%') .margin({ top: 30 }) Image($r('app.media.computer2')) .height(220) .width('100%') .margin({ top: 30 }) Image($r('app.media.computer3')) .height(220) .width('100%') .margin({ top: 30 }) Image($r('app.media.computer4')) .height(220) .width('100%') .margin({ top: 30 }) Image($r('app.media.computer5')) .height(220) .width('100%') .margin({ top: 30 }) Image($r('app.media.computer6')) .height(220) .width('100%') .margin({ top: 30 }) } .width('100%') .flexGrow(1) } .scrollable(ScrollDirection.Vertical) DetailBottom() } .height('90%') .width('100%') } }
其中頂部DetailTop組件效果圖如下:
代碼如下:
@Component struct DetailTop { build() { Column() { Row() { Image($r('app.media.icon_return')) .height(40) .width(40) .margin({left: 20}) .onClick(() = > { router.push({ uri: "pages/HomePage" }) }) } .width('100%') .height(35) .backgroundColor('#FF87CEEB') } .width('100%') .height(40) } }
SwiperTop組件效果圖如下:
代碼如下:@Component struct SwiperTop { build() { Column() { Swiper() { Image($r('app.media.computer1')) .height(220) .width('100%') Image($r('app.media.computer2')) .height(220) .width('100%') Image($r('app.media.computer3')) .height(220) .width('100%') Image($r('app.media.computer4')) .height(220) .width('100%') Image($r('app.media.computer5')) .height(220) .width('100%') Image($r('app.media.computer6')) .height(220) .width('100%') } .index(0) .autoPlay(true) .interval(3000) .indicator(true) .loop(true) .height(250) .width('100%') } .height(250) .width('100%') } }
DetailText組件效果圖如下:
代碼如下:@Component struct DetailText { build() { Column() { Row() { Image($r('app.media.icon_promotion')) .objectFit(ImageFit.Contain) .height(30) .width(30) .margin({ left: 10 }) Text('Special Offer: ¥9999') .fontColor(Color.White) .fontSize(20) .margin({ left: 10 }) } .width('100%') .height(35) .backgroundColor(Color.Red) Column() { Text('New Arrival: HUAWEI MateBook X Pro 2021') .fontSize(18) .margin({ left: 10 }) .alignSelf(ItemAlign.Start) Text('13.9-Inch, 11th Gen Intel? Core? i7, 16 GB of Memory, 512 GB of Storage, Ultra-slim Business Laptop, 3K FullView Display, Multi-screen Collaboration, Emerald Green') .fontSize(14) .margin({ left: 10 }) Row() { Image($r('app.media.icon_buy')) .objectFit(ImageFit.Contain) .height(30) .width(30) .margin({ left: 10 }) Text('Limited offer') .fontSize(15) .fontColor(Color.Red) .margin({ left: 100 }) } .backgroundColor(Color.Pink) .width('100%') .height(45) .margin({ top: 10 }) Text(' Shipment: 2-day shipping') .fontSize(13) .fontColor(Color.Red) .margin({ left: 10, top: 5 }) .alignSelf(ItemAlign.Start) Text(' Ship To: Hubei,Wuhan,China') .fontSize(13) .fontColor(Color.Red) .margin({ left: 10, top: 5 }) .alignSelf(ItemAlign.Start) .onClick(() = > { prompt.showDialog({ title: 'select address', }) }) Text('Guarantee: Genuine guaranteed') .fontSize(13) .margin({ left: 10, top: 5 }) .alignSelf(ItemAlign.Start) } .height(170) .width('100%') } .height(180) .width('100%') } }
DetailArsList組件效果圖如下:
代碼如下:
@Component struct DetailArsList{ private arsItems: ArsData[] build() { Scroll() { Column() { List() { ForEach(this.arsItems, item = > { ListItem() { ArsListItem({ arsItem: item }) } }, item = > item.id.toString()) } .height('100%') .width('100%') .margin({ top: 5 }) .listDirection(Axis.Vertical) } .height(200) } } }
ArsListItem組件代碼如下:
@Component struct ArsListItem { private arsItem: ArsData build() { Row() { Text(this.arsItem.title + " :") .fontSize(11) .margin({ left: 20 }) .flexGrow(1) Text(this.arsItem.content) .fontSize(11) .margin({ right: 20 }) } .height(14) .width('100%') .backgroundColor(Color.White) } }
DetailBottom組件效果圖如下:
代碼如下:@Component struct DetailBottom { @Provide private value: number= 1 dialogController: CustomDialogController = new CustomDialogController({ builder: DialogExample({ action: this.onAccept }), cancel: this.existApp, autoCancel: true }); onAccept() { } existApp() { } build() { Column() { Text('Buy') .width(40) .height(25) .fontSize(20) .fontColor(Color.White) .onClick(() = > { this.value = 1 this.dialogController.open() }) } .alignItems(HorizontalAlign.Center) .backgroundColor(Color.Red) .width('100%') .height('10%') } }
DialogExample自定義彈窗組件效果圖如下:
代碼如下:
@CustomDialog struct DialogExample { @Consume private value: number controller: CustomDialogController; action: () = > void; build() { Column() { Progress({ value: this.value++ >= 100 ? 100 : this.value, total: 100, style: ProgressStyle.Capsule }) .height(50) .width(100) .margin({ top: 5 }) } .height(60) .width(100) } }
審核編輯 黃宇
-
鴻蒙
+關注
關注
57文章
2464瀏覽量
43584 -
HarmonyOS
+關注
關注
79文章
2005瀏覽量
31688
發布評論請先 登錄
相關推薦
評論