如何使用ArkUI从0-1写一个开发购物应用程序(下)

567 篇文章 8 订阅
555 篇文章 0 订阅

接下来我们继续学习如何用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)
  }
}

实现购物车页签

主界面购物车页签主要由下面三部分组成:

  • 顶部的Text组件。
  • 中间的List组件,其中List组件的item是一个水平的布局内包含一个toggle组件,一个Image组件和一个垂直布局,其item中的垂直布局是由2个Text组件组成。
  • 底部一个水平布局包含两个Text组件。

构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部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)
  }
}

实现我的页签

我的页签主要由下面四部分组成:

  • 顶部的水平布局。
  • 顶部下面的文本加数字的水平List。
  • My Transactio模块,图片加文本的水平List。
  • More模块,图片加文本的Grid。

构建主页我的页签,主要可以划分成下面几步:

  • 在pages目录下面新建一个Page 命名为MyPage
  • 在MyPage.ets文件中添加入口组件(MyInfo)

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)
  }
}

实现商品详情页面

商品详情页面主要由下面五部分组成:

  • 顶部的返回栏。
  • Swiper组件。
  • 中间多个Text组件组成的布局。
  • 参数列表。
  • 底部的Buy。

把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部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目录下。

删除index.ets

因为程序的入口文件已经改为了HomePage.ets文件,因此需要删除Index.ets文件。

HomePage.ets文件重新命名

把HomePage.ets文件重新命名为Index.ets文件。

程序运行效果

以上内容是介绍了如何用ArkUI来开发一个购物应用程序全部教程

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了几套最新版的HarmonyOS NEXT学习资源

获取完整版高清学习路线,请点击→《HarmonyOS教学视频

HarmonyOS教学视频

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取白皮书:请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?鸿蒙基础入门学习指南

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值