赞
踩
接下来我们继续学习如何用ArkUI来开发一个购物应用程序(下半部分)
底部组件是由一个横向的图片列表组成,iconPath是底部初始状态下的3张图片路径数组。遍历iconPath数组,使用Image组件设置图片路径并添加到List中,给每个Image组件设置点击事件,点击更换底部3张图片。在HomeBottom中,iconPath使用的是@State修饰,当iconPath数组内容变化时,页面组件有使用到的地方都会随之发生变化。
在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%')
- .align(Alignment.Top)
- .margin({ top: 5})
- .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 MenuItem {
- private menu: Menu
- build() {
- Column() {
- Text(this.menu.title)
- .fontSize(15)
- Text(this.menu.num+'')
- .fontSize(13)
- }
- .height(50)
- .width(80)
- .margin({left: 8,right:8})
- .alignItems(HorizontalAlign.Start)
- .backgroundColor(Color.White)
- }
- }
主界面购物车页签主要由下面三部分组成:
构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部Total值也会随之增加或减少,点击Check Out时会触发弹窗。下面我们来完成ShoppingCart页签。
在pages目录下面新建一个Page ,命名为ShoppingCart.。在ShoppingCart.ets文件中添加入口组件(ShoppingCart),并导入需要使用到的数据实体类、方法和组件。ShoppingCart组件代码如下:
- @Entry
- @Component
- export struct ShoppingCart {
- @Provide totalPrice : number =0
- private goodsItems: GoodsData[] = initializeOnStartup()
- build() {
- Column() {
- Column() {
- Text('ShoppingCart')
- .fontColor(Color.Black)
- .fontSize(25)
- .margin({ left: 60,right:60 })
- .align(Alignment.Center)
- }
- .backgroundColor('#FF00BFFF')
- .width('100%')
- .height(30)
-
- ShopCartList({ goodsItems: this.goodsItems });
- ShopCartBottom()
- }
- .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(570)
- }
- }
ShopCartListItem组件代码如下:
- @Component
- struct ShopCartListItem {
- @Consume totalPrice: number
- private goodsItem: GoodsData
- build() {
- Row() {
- Toggle({type: ToggleType.Checkbox})
- .width(10)
- .height(10)
- .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(100)
- .width(100)
- .renderMode(ImageRenderMode.Original)
- Column() {
- Text(this.goodsItem.title)
- .fontSize(14)
- Text('¥' + this.goodsItem.price)
- .fontSize(14)
- .fontColor(Color.Red)
- }
- }
- .height(100)
- .width(180)
- .margin({left: 20})
- .alignItems(VerticalAlign.Center)
- .backgroundColor(Color.White)
- }
- }
在ShopCartListItem中使用Toggle的单选框类型来实现每个item的选择和取消选择,在Toggle的onChage事件中来改变totalPrice的数值。
新建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:100})
- .onClick(()=>{
- prompt.showToast({
- message: 'Checking Out',
- duration: 10,
- bottom:100
- })
- })
- }
- .height(30)
- .width('100%')
- .backgroundColor('#FF7FFFD4')
- .alignItems(VerticalAlign.Bottom)
- }
- }
我的页签主要由下面四部分组成:
构建主页我的页签,主要可以划分成下面几步:
MyInfo组件内容如下:
- import {getMenu,getTrans,getMore} from '../model/GoodsDataModels'
- import {Menu, ImageItem} from '../model/Menu'
- @Entry
- @Component
- export struct MyInfo {
- build() {
- Column() {
- Row(){
- Image($rawfile('nav/icon-user.png'))
- .margin({left:20})
- .objectFit(ImageFit.Cover)
- .height(50)
- .width(50)
- .renderMode(ImageRenderMode.Original)
- .margin({left:40,right:40})
- Column(){
- Text('John Doe')
- .fontSize(15)
- Text('Member Name : John Doe >')
- }
- .height(60)
- .margin({left:40,top:10})
- .alignItems(HorizontalAlign.Start)
- }
- TopList()
- MyTransList()
- MoreGrid()
-
- }
- .alignItems(HorizontalAlign.Start)
- .width('100%')
- .flexGrow(1)
- }
- }
入口组件中还包含TopList,MyTransList和MoreGrid三个子组件。代码如下:
- @Component
- struct TopList {
- private menus: Menu[] = getMenu()
- build() {
- Row() {
- List() {
- ForEach(this.menus, item => {
- ListItem() {
- MenuItem({ menu: item })
- }
- }, item => item.id.toString())
- }
- .height('100%')
- .width('100%')
- .margin({top: 5})
- .edgeEffect(EdgeEffect.None)
- .listDirection(Axis.Horizontal)
- }
- .width('100%')
- .height(50)
- }
- }
- @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%')
- .align(Alignment.Top)
- .margin({ top: 5})
- .listDirection(Axis.Horizontal)
- }
- }
- .height(120)
- }
- }
- @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)
- }
- }
商品详情页面主要由下面五部分组成:
把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部Buy时,会触发进度条弹窗。
在pages目录下面新建一个Page, 命名为ShoppingDetail。在ShoppingDetail.ets文件中创建入口组件,组件内容如下:
- import router from '@system.router';
- import {ArsData} from '../model/ArsData'
- import {getArs,getDetailImages} from '../model/GoodsDataModels'
- import prompt from '@system.prompt';
- @Entry
- @Component
- struct ShoppingDetail {
- private arsItems: ArsData[] = getArs()
- private detailImages: string[] = getDetailImages()
- build() {
- Column() {
- DetailTop()
- Scroll() {
- Column() {
- SwiperTop()
- DetailText()
- DetailArsList({ arsItems: this.arsItems })
- Image($rawfile('computer/computer1.png'))
- .height(220)
- .width('100%')
- .margin({top:30})
- Image($rawfile('computer/computer2.png'))
- .height(220)
- .width('100%')
- .margin({top:30})
- Image($rawfile('computer/computer3.png'))
- .height(220)
- .width('100%')
- .margin({top:30})
- Image($rawfile('computer/computer4.png'))
- .height(220)
- .width('100%')
- .margin({top:30})
- Image($rawfile('computer/computer5.png'))
- .height(220)
- .width('100%')
- .margin({top:30})
- Image($rawfile('computer/computer6.png'))
- .height(220)
- .width('100%')
- .margin({top:30})
- }
- .width('100%')
- .flexGrow(1)
- }
- .scrollable(ScrollDirection.Vertical)
- DetailBottom()
- }
- .height(630)
- }
- }
顶部DetailTop组件代码如下:
- @Component
- struct DetailTop{
- build(){
- Column(){
- Row(){
- Image($rawfile('detail/icon-return.png'))
- .height(20)
- .width(20)
- .margin({ left: 20, right: 250 })
- .onClick(() => {
- router.push({
- uri: "pages/HomePage"
- })
- })
- }
- .width('100%')
- .height(25)
- .backgroundColor('#FF87CEEB')
- }
- .width('100%')
- .height(30)
- }
- }
SwiperTop组件代码如下:
- @Component
- struct SwiperTop{
- build() {
- Column() {
- Swiper() {
- Image($rawfile('computer/computer1.png'))
- .height(220)
- .width('100%')
- Image($rawfile('computer/computer2.png'))
- .height(220)
- .width('100%')
- Image($rawfile('computer/computer3.png'))
- .height(220)
- .width('100%')
- Image($rawfile('computer/computer4.png'))
- .height(220)
- .width('100%')
- Image($rawfile('computer/computer5.png'))
- .height(220)
- .width('100%')
- Image($rawfile('computer/computer6.png'))
- .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($rawfile('computer/icon-promotion.png'))
- .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(15)
- .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(10)
- .margin({left:10})
- Row(){
- Image($rawfile('nav/icon-buy.png'))
- .height(15)
- .width(15)
- .margin({left:10})
- //TODO 暂不支持跑马灯组件,用Text代替
- Text('Limited offer')
- .fontSize(10)
- .fontColor(Color.Red)
- .margin({left:100})
- }
- .backgroundColor(Color.Pink)
- .width('100%')
- .height(25)
- .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(150)
- .width('100%')
- }
- .height(160)
- .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(40)
- }
- }
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.Eclipse})
- .height(50)
- .width(100)
- .margin({top:5})
- }
- .height(60)
- .width(100)
- }
- }
程序中所用到的资源文件都放置到resources\rawfile目录下。
因为程序的入口文件已经改为了HomePage.ets文件,因此需要删除Index.ets文件。
把HomePage.ets文件重新命名为Index.ets文件。
以上内容是介绍了如何用ArkUI来开发一个购物应用程序全部教程
为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了几套最新版的HarmonyOS NEXT学习资源
获取完整版高清学习路线,请点击→《HarmonyOS教学视频》
获取白皮书:请点击→《鸿蒙生态应用开发白皮书V2.0PDF》
一、入门必看
二、HarmonyOS 概念
三、如何快速入门?《鸿蒙基础入门学习指南》
四、开发基础知识
五、基于ArkTS 开发
更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。