当前位置:   article > 正文

OpenHarmony开发实战:购物应用(ArkTS)_构建一个简易的购物应用。应用包含两级页面,分别是主页(商品浏览页签、购物车进入

构建一个简易的购物应用。应用包含两级页面,分别是主页(商品浏览页签、购物车进入

OpenHarmony ArkUI框架提供了丰富的动画组件和接口,开发者可以根据实际场景和开发需求,选用丰富的动画组件和接口来实现不同的动画效果。

本文中,我们会构建一个简易的购物应用。应用包含两级页面,分别是主页(“商品浏览”页签、“购物车”页签、“我的”页签)和商品详情页面。效果如下图所示:

代码结构解读

本篇Codelab只对核心代码进行讲解,首先来介绍下整个工程的代码结构:

  • model:存放封装好的数据实体。

    • ArsData:我的页签相关参数实体。
    • GoodsData:商品列表页商品实体。
    • GoodsDataModels:各种实体的具体数据以及获取数据的方法。
    • Menu:我的页签菜单实体。
  • pages:存放页面。

    • HomePage:应用主页面,包含商品列表页签。
    • MyPage:我的页签。
    • ShoppingCartPage:购物车页签。
    • ShoppingDetail:商品详情页。
  • resources :存放工程使用到的资源文件。

    • resources/base/media:存放工程中使用的图片资源。
  • config.json:配置文件。

搭建OpenHarmony环境

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以Hi3516DV300开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)

    以3.0版本为例:

  2. 搭建烧录环境

    1. 完成DevEco Device Tool的安装
    2. 完成Hi3516开发板的烧录
  3. 搭建开发环境

    1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”),选择JS或者eTS语言开发。
    3. 工程创建完成后,选择使用真机进行调测

构建商品列表页签

在本节中,我们将完成商品列表页签的设计,效果图如下:

从效果图可以看出,商品列表页签主要由三个部分组成:

  1. 顶部的Tabs组件。
  2. 中间TabContent组件内包含List组件。其中List组件的item是一个水平布局,由一个垂直布局和一个Image组件组成;item中的垂直布局由3个Text组件组成。
  3. 底部的导航页签navigation组件。

实现步骤如下:

  1. 在pages目录下面新建一个ETS Page,命名为HomePage.ets,在config.json文件的pages属性中会自动添加“pages/HomePage”页面路由。

    说明:

    • 页面文件名不能使用组件名称,比如:Text.ets、Button.ets等。
    • 每个页面文件中必须包含入口组件。
  2. 新建与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内容如下:

    1. let NextId = 0;
    2. export class ArsData {
    3. id: string;
    4. title: string;
    5. content: string;
    6. constructor(title: string, content: string) {
    7. this.id = `${NextId++}`;
    8. this.title = title;
    9. this.content = content;
    10. }
    11. }

    GoodsData.ets代码如下:

    1. let NextId = 0;
    2. export class GoodsData {
    3. id: string;
    4. title: string;
    5. content: string;
    6. price: number;
    7. imgSrc: Resource;
    8. constructor(title: string, content: string, price: number, imgSrc: Resource) {
    9. this.id = `${NextId++}`;
    10. this.title = title;
    11. this.content = content;
    12. this.price = price;
    13. this.imgSrc = imgSrc;
    14. }
    15. }

    一个文件中可以包含多个class ,Menu.ets中就包含了Menu类和ImageItem类,Menu.ets代码如下

    1. let NextId = 0;
    2. export class Menu {
    3. id: string;
    4. title: string;
    5. num: number;
    6. constructor(title: string, num: number) {
    7. this.id = `${NextId++}`;
    8. this.title = title;
    9. this.num = num;
    10. }
    11. }
    12. export class ImageItem {
    13. id: string;
    14. title: string;
    15. imageSrc: Resource;
    16. constructor(title: string, imageSrc: Resource) {
    17. this.id = `${NextId++}`;
    18. this.title = title;
    19. this.imageSrc = imageSrc;
    20. }
    21. }

    GoodsDataModels.ets代码如下:

    1. import {GoodsData} from './GoodsData'
    2. import {Menu, ImageItem} from './Menu'
    3. import {ArsData} from './ArsData'
    4. //获取商品列表数据
    5. export function initializeOnStartup(): Array<GoodsData> {
    6. let GoodsDataArray: Array<GoodsData> = []
    7. GoodsComposition.forEach(item => {
    8. console.log(item.title);
    9. GoodsDataArray.push(new GoodsData(item.title, item.content, item.price, item.imgSrc));
    10. })
    11. return GoodsDataArray;
    12. }
    13. //获取底部默认图片列表数据
    14. export function getIconPath(): Array<string> {
    15. let IconPath: Array<string> = ['nav/icon-buy.png','nav/icon-shopping-cart.png','nav/icon-my.png']
    16. return IconPath;
    17. }
    18. //获取选中后图片列表数据
    19. export function getIconPathSelect(): Array<string> {
    20. let IconPathSelect: Array<string> = ['nav/icon-home.png','nav/icon-shopping-cart-select.png','nav/icon-my-select.png']
    21. return IconPathSelect;
    22. }
    23. //获取商品详情页图片详情列表
    24. export function getDetailImages(): Array<string> {
    25. let detailImages: Array<string> = ['computer/computer1.png','computer/computer2.png','computer/computer3.png','computer/computer4.png','computer/computer5.png','computer/computer6.png']
    26. return detailImages;
    27. }
    28. //获取菜单数据列表
    29. export function getMenu(): Array<Menu> {
    30. let MenuArray: Array<Menu> = []
    31. MyMenu.forEach(item => {
    32. MenuArray.push(new Menu(item.title,item.num));
    33. })
    34. return MenuArray;
    35. }
    36. //获取MyTrans数据列表
    37. export function getTrans(): Array<ImageItem> {
    38. let ImageItemArray: Array<ImageItem> = []
    39. MyTrans.forEach(item => {
    40. ImageItemArray.push(new ImageItem(item.title,item.imageSrc));
    41. })
    42. return ImageItemArray;
    43. }
    44. //获取More数据列表
    45. export function getMore(): Array<ImageItem> {
    46. let ImageItemArray: Array<ImageItem> = []
    47. MyMore.forEach(item => {
    48. ImageItemArray.push(new ImageItem(item.title,item.imageSrc));
    49. })
    50. return ImageItemArray;
    51. }
    52. //获取参数列表
    53. export function getArs(): Array<ArsData> {
    54. let ArsItemArray: Array<ArsData> = []
    55. ArsList.forEach(item => {
    56. ArsItemArray.push(new ArsData(item.title,item.content));
    57. })
    58. return ArsItemArray;
    59. }
    60. //数据集合部分
    61. ...
  3. 在HomePage.ets文件中创建商品列表页签相关的组件,其中GoodsHome效果图如下:

    代码如下:

    1. @Component
    2. @Component
    3. struct GoodsHome {
    4. private goodsItems: GoodsData[]
    5. build() {
    6. Column() {
    7. Tabs() {
    8. TabContent() {
    9. GoodsList({ goodsItems: this.goodsItems });
    10. }
    11. .tabBar("Top Sellers")
    12. .backgroundColor(Color.White)
    13. TabContent() {
    14. GoodsList({ goodsItems: this.goodsItems });
    15. }
    16. .tabBar("Recommended")
    17. .backgroundColor(Color.White)
    18. TabContent() {
    19. GoodsList({ goodsItems: this.goodsItems });
    20. }
    21. .tabBar("Lifestyle")
    22. .backgroundColor(Color.White)
    23. TabContent() {
    24. GoodsList({ goodsItems: this.goodsItems });
    25. }
    26. .tabBar("Deals")
    27. .backgroundColor(Color.White)
    28. }
    29. .barWidth(540)
    30. .barHeight(50)
    31. .scrollable(true)
    32. .barMode(BarMode.Scrollable)
    33. .backgroundColor('#007DFF')
    34. .height('100%')
    35. }
    36. .alignItems(HorizontalAlign.Start)
    37. }
    38. }

    在GoodsHome中使用Tabs组件,在Tabs组件中设置4个TabContent,给每个TabContent设置tabBar属性,并设置TabContent容器中的内容GoodsList组件,GoodsList组件效果图如下:

    代码如下:

    1. @Component
    2. struct GoodsList {
    3. private goodsItems: GoodsData[]
    4. build() {
    5. Column() {
    6. List() {
    7. ForEach(this.goodsItems, item => {
    8. ListItem() {
    9. GoodsListItem({ goodsItem: item })
    10. }
    11. }, item => item.id.toString())
    12. }
    13. .height('100%')
    14. .width('100%')
    15. .align(Alignment.Top)
    16. .margin({top: 5})
    17. }
    18. }
    19. }

    在GoodsList组件中遍历商品数据集合,ListItem组件中设置组件内容,并使用Navigator组件给每个Item设置顶级跳转路由,GoodsListItem组件效果图如下:

    代码如下:

    1. @Component
    2. struct GoodsListItem {
    3. private goodsItem: GoodsData
    4. build() {
    5. Navigator({ target: 'pages/ShoppingDetail' }) {
    6. Row() {
    7. Column() {
    8. Text(this.goodsItem.title)
    9. .fontSize(18)
    10. Text(this.goodsItem.content)
    11. .fontSize(14)
    12. Text('¥' + this.goodsItem.price)
    13. .fontSize(18)
    14. .fontColor(Color.Red)
    15. }
    16. .height(130)
    17. .width('60%')
    18. .margin({ left: 20 })
    19. .alignItems(HorizontalAlign.Start)
    20. Image(this.goodsItem.imgSrc)
    21. .objectFit(ImageFit.ScaleDown)
    22. .height(130)
    23. .width('30%')
    24. .renderMode(ImageRenderMode.Original)
    25. .margin({ right: 10, left: 10 })
    26. }
    27. .backgroundColor(Color.White)
    28. }
    29. .params({ goodsData: this.goodsItem })
    30. .margin({ right: 5 })
    31. }
    32. }
  4. 在HomePage.ets中创建文件入口组件(Index)以及底部页签导航组件(Navigation),导入需要使用到的数据实体类以及需要使用的方法和组件,每个page文件都必须包含一个入口组件,使用@Entry修饰,HomePage文件中的入口组件(Index)代码如下:

    1. import { GoodsData, IconImage } from '../model/GoodsData'
    2. import { initializeOnStartup, getIconPath, getIconPathSelect } from '../model/GoodsDataModels'
    3. import { ShoppingCart } from './ShoppingCartPage.ets'
    4. import { MyInfo } from './MyPage.ets'
    5. import router from '@system.router';
    6. @Entry
    7. @Component
    8. struct Index {
    9. @Provide currentPage: number = 1
    10. private goodsItems: GoodsData[] = initializeOnStartup()
    11. @State Build: Array<Object> = [
    12. {
    13. icon: $r('app.media.icon_home'),
    14. icon_after: $r('app.media.icon_buy1'),
    15. text: '首页',
    16. num: 0
    17. },
    18. {
    19. icon: $r('app.media.icon_shopping_cart'),
    20. icon_after: $r('app.media.icon_shopping_cart_select'),
    21. text: '购物车',
    22. num: 1
    23. },
    24. {
    25. icon: $r('app.media.icon_my'),
    26. icon_after: $r('app.media.icon_my_select'),
    27. text: '我的',
    28. num: 2
    29. }
    30. ]
    31. @Builder NavigationToolbar() {
    32. Flex({direction:FlexDirection.Row,wrap:FlexWrap.NoWrap,justifyContent:FlexAlign.SpaceAround}) {
    33. ForEach(this.Build, item => {
    34. Column() {
    35. Image(this.currentPage == item.num ? item.icon_after : item.icon)
    36. .width(25)
    37. .height(25)
    38. Text(item.text)
    39. .fontColor(this.currentPage == item.num ? "#ff7500" : "#000000")
    40. }
    41. .onClick(() => {
    42. this.currentPage = item.num
    43. })
    44. })
    45. }
    46. }
    47. build() {
    48. Column() {
    49. Navigation() {
    50. Flex() {
    51. if (this.currentPage == 0) {
    52. GoodsHome({ goodsItems: this.goodsItems })
    53. }
    54. if (this.currentPage == 1) {
    55. ShoppingCart() //购物车列表
    56. }
    57. if (this.currentPage == 2) {
    58. MyInfo() //我的
    59. }
    60. }
    61. .width('100%')
    62. .height('100%')
    63. }
    64. .toolBar(this.NavigationToolbar)
    65. .title("购物车")
    66. .hideTitleBar(this.currentPage == 1 ? false : true)
    67. .hideBackButton(true)
    68. }
    69. }
    70. }

    从入口组件的代码中可以看出,我们定义了一个全局变量currentPage ,当currentPage发生变化的时候,会显示不同的页签。在入口组件中,通initializeOnStartup获取商品列表数据(goodsItems)并传入GoodsHome组件中。效果图如下:

构建购物车页签

从上面效果图可以看出,主界面购物车页签主要由下面三部分组成:

  1. 顶部的title,由Navigation组件title属性设置。
  2. 中间的List组件,其中List组件的item是一个水平的布局内包含一个toggle组件,一个Image组件和一个垂直布局,其item中的垂直布局是由2个Text组件组成。
  3. 底部一个水平布局包含两个Text组件。

在本任务中我们主要是构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部Total值也会随之增加或减少,点击Check Out时会触发弹窗。下面我们来完成ShoppingCart页签。

  1. 在pages目录下面新建一个ETS Page ,命名为ShoppingCart.ets,config.json文件pages属性中也会自动添加“pages/ShoppingCart”页面路由。

  2. 在ShoppingCartPage.ets文件中添加入口组件(ShoppingCart),并导入需要使用到的数据实体类、方法和组件。ShoppingCart组件代码如下:

    1. import {GoodsData} from '../model/GoodsData'
    2. import {initializeOnStartup} from '../model/GoodsDataModels'
    3. import prompt from '@system.prompt';
    4. @Entry
    5. @Component
    6. export struct ShoppingCart {
    7. @Provide totalPrice: number = 0
    8. private goodsItems: GoodsData[] = initializeOnStartup()
    9. build() {
    10. Column() {
    11. ShopCartList({ goodsItems: this.goodsItems });
    12. ShopCartBottom()
    13. }
    14. .height('100%')
    15. .width('100%')
    16. .alignItems(HorizontalAlign.Start)
    17. }
    18. }
  3. 新建ShopCartList组件用于存放购物车商品列表,ShopCartList组件效果图如下:

    代码如下:

    1. @Component
    2. struct ShopCartList {
    3. private goodsItems: GoodsData[]
    4. build() {
    5. Column() {
    6. List() {
    7. ForEach(this.goodsItems, item => {
    8. ListItem() {
    9. ShopCartListItem({ goodsItem: item })
    10. }
    11. }, item => item.id.toString())
    12. }
    13. .height('100%')
    14. .width('100%')
    15. .align(Alignment.Top)
    16. .margin({ top: 5 })
    17. }
    18. .height('90%')
    19. }
    20. }

    在ShopCartListItem中使用Toggle的单选框类型来实现每个item的选择和取消选择,在Toggle的onChage事件中来改变totalPrice的数值。ShopCartListItem组件效果图如下:

    代码如下:

    1. @Component
    2. struct ShopCartListItem {
    3. @Consume totalPrice: number
    4. private goodsItem: GoodsData
    5. build() {
    6. Row() {
    7. Toggle({ type: ToggleType.Checkbox })
    8. .width(13)
    9. .height(13)
    10. .onChange((isOn: boolean) => {
    11. if (isOn) {
    12. this.totalPrice += parseInt(this.goodsItem.price + '', 0)
    13. } else {
    14. this.totalPrice -= parseInt(this.goodsItem.price + '', 0)
    15. }
    16. })
    17. Image(this.goodsItem.imgSrc)
    18. .objectFit(ImageFit.ScaleDown)
    19. .height(130)
    20. .width(100)
    21. .renderMode(ImageRenderMode.Original)
    22. Column() {
    23. Text(this.goodsItem.title)
    24. .fontSize(18)
    25. Text('¥' + this.goodsItem.price)
    26. .fontSize(18)
    27. .fontColor(Color.Red)
    28. }
    29. .margin({left:40})
    30. }
    31. .height(100)
    32. .width('100%')
    33. .margin({ left: 20 })
    34. .alignItems(VerticalAlign.Center)
    35. .backgroundColor(Color.White)
    36. }
    37. }
  4. 新建ShopCartBottom组件,ShopCartBottom组件效果图如下:

    代码如下:

    1. @Component
    2. struct ShopCartBottom {
    3. @Consume totalPrice: number
    4. build() {
    5. Row() {
    6. Text('Total: ¥' + this.totalPrice)
    7. .fontColor(Color.Red)
    8. .fontSize(18)
    9. .margin({ left: 20 })
    10. .width(150)
    11. Text('Check Out')
    12. .fontColor(Color.Black)
    13. .fontSize(18)
    14. .margin({ right: 20, left: 180 })
    15. .onClick(() => {
    16. prompt.showToast({
    17. message: 'Checking Out',
    18. duration: 10,
    19. bottom: 100
    20. })
    21. })
    22. }
    23. .height(30)
    24. .width('100%')
    25. .backgroundColor('#FF7FFFD4')
    26. .alignItems(VerticalAlign.Bottom)
    27. }
    28. }

构建我的页签

从上面效果图可以看出,主界面我的页签主要由下面四部分组成:

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

在本任务中,我们构建主页我的页签,主要可以划分成下面几步:

  1. 在pages目录下面新建一个ETS Page 命名为MyPage.ets,在config.json文件pages属性中也会自动添加“pages/MyPage”页面路由。

  2. 在MyPage.ets文件中添加入口组件(MyInfo),组件内容如下:

    1. import {getMenu,getTrans,getMore} from '../model/GoodsDataModels'
    2. import {Menu, ImageItem} from '../model/Menu'
    3. @Entry
    4. @Component
    5. export struct MyInfo {
    6. build() {
    7. Column() {
    8. Row() {
    9. Image($r('app.media.icon_user'))
    10. .objectFit(ImageFit.Contain)
    11. .height(50)
    12. .width(50)
    13. .margin({left:10})
    14. .renderMode(ImageRenderMode.Original)
    15. Column() {
    16. Text('John Doe')
    17. .fontSize(15)
    18. Text('Member Name : John Doe >')
    19. .fontSize(15)
    20. }
    21. .height(60)
    22. .margin({ left: 20, top: 10 })
    23. .alignItems(HorizontalAlign.Start)
    24. }
    25. TopList()
    26. MyTransList()
    27. MoreGrid()
    28. }
    29. .alignItems(HorizontalAlign.Start)
    30. .width('100%')
    31. .height('100%')
    32. .flexGrow(1)
    33. }
    34. }

    入口组件中还包含TopList,MyTransList和MoreGrid三个子组件。

  3. 在MyPage.ets文件中新建TopList组件,效果图如下:

    代码如下:

    1. @Component
    2. struct TopList {
    3. private menus: Menu1[] = getMenu()
    4. build() {
    5. Row() {
    6. List() {
    7. ForEach(this.menus, item => {
    8. ListItem() {
    9. MenuItem({ menu: item })
    10. }
    11. }, item => item.id.toString())
    12. }
    13. .height('100%')
    14. .width('100%')
    15. .margin({ top: 5,left: 10})
    16. .edgeEffect(EdgeEffect.None)
    17. .listDirection(Axis.Horizontal)
    18. }
    19. .width('100%')
    20. .height(50)
    21. }
    22. }

    getMenu()方法在上文中已有定义,是获取菜单列表的方法,TopList的子组件MenuItem内容如下:

    1. @Component
    2. struct MenuItem {
    3. private menu: Menu1
    4. build() {
    5. Column() {
    6. Text(this.menu.title)
    7. .fontSize(15)
    8. Text(this.menu.num + '')
    9. .fontSize(13)
    10. }
    11. .height(50)
    12. .width(100)
    13. .margin({ left: 8, right: 8 })
    14. .alignItems(HorizontalAlign.Start)
    15. .backgroundColor(Color.White)
    16. }
    17. }
  4. 在MyPage.ets文件中新建MyTransList组件和MoreGrid组件,MyTransList组件效果如如下:

    代码如下:

    1. @Component
    2. struct MyTransList {
    3. private imageItems: ImageItem[] = getTrans()
    4. build() {
    5. Column() {
    6. Text('My Transaction')
    7. .fontSize(20)
    8. .margin({ left: 10 })
    9. .width('100%')
    10. .height(30)
    11. Row() {
    12. List() {
    13. ForEach(this.imageItems, item => {
    14. ListItem() {
    15. DataItem({ imageItem: item })
    16. }
    17. }, item => item.id.toString())
    18. }
    19. .height(70)
    20. .width('100%')
    21. .edgeEffect(EdgeEffect.None)
    22. .margin({ top: 5 })
    23. .padding({ left: 16, right: 16 })
    24. .listDirection(Axis.Horizontal)
    25. }
    26. }
    27. .height(120)
    28. }
    29. }

    MoreGrid组件效果图如下:

    代码如下:

    1. @Component
    2. struct MoreGrid {
    3. private gridRowTemplate: string = ''
    4. private imageItems: ImageItem[] = getMore()
    5. private heightValue: number
    6. aboutToAppear() {
    7. var rows = Math.round(this.imageItems.length / 3);
    8. this.gridRowTemplate = '1fr '.repeat(rows);
    9. this.heightValue = rows * 75;
    10. }
    11. build() {
    12. Column() {
    13. Text('More')
    14. .fontSize(20)
    15. .margin({ left: 10 })
    16. .width('100%')
    17. .height(30)
    18. Scroll() {
    19. Grid() {
    20. ForEach(this.imageItems, (item: ImageItem) => {
    21. GridItem() {
    22. DataItem({ imageItem: item })
    23. }
    24. }, (item: ImageItem) => item.id.toString())
    25. }
    26. .rowsTemplate(this.gridRowTemplate)
    27. .columnsTemplate('1fr 1fr 1fr')
    28. .columnsGap(8)
    29. .rowsGap(8)
    30. .height(this.heightValue)
    31. }
    32. .padding({ left: 16, right: 16 })
    33. }
    34. .height(400)
    35. }
    36. }

    在MyTransList和MoreGrid组件中都包含子组件DataItem,为避免的重复代码,可以把多次要用到的结构体组件化,这里的结构体就是图片加上文本的上下结构体,DataItem组件内容如下:

    1. @Component
    2. struct DataItem {
    3. private imageItem: ImageItem
    4. build() {
    5. Column() {
    6. Image(this.imageItem.imageSrc)
    7. .objectFit(ImageFit.Contain)
    8. .height(50)
    9. .width(50)
    10. .renderMode(ImageRenderMode.Original)
    11. Text(this.imageItem.title)
    12. .fontSize(15)
    13. }
    14. .height(70)
    15. .width(150)
    16. .margin({ left: 10, right: 10 })
    17. .backgroundColor(Color.White)
    18. }
    19. }

构建商品详情页面

从上面效果图可以看出,商品详情页面主要由下面五部分组成:

  1. 顶部的返回栏。
  2. Swiper组件。
  3. 中间多个Text组件组成的布局。
  4. 参数列表。
  5. 底部的Buy。

在本任务中,把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部Buy时,会触发进度条弹窗

  1. 在pages目录下面新建一个ETS Page, 命名为ShoppingDetail.ets,config.json文件pages属性中也会自动添加“pages/ShoppingDetail”页面路由。

  2. 在ShoppingDetail.ets文件中创建入口组件,组件内容如下:

    1. @Entry
    2. @Component
    3. struct ShoppingDetail {
    4. private arsItems: ArsData[] = getArs()
    5. build() {
    6. Column() {
    7. DetailTop()
    8. Scroll() {
    9. Column() {
    10. SwiperTop()
    11. DetailText()
    12. DetailArsList({ arsItems: this.arsItems })
    13. Image($r('app.media.computer1'))
    14. .height(220)
    15. .width('100%')
    16. .margin({ top: 30 })
    17. Image($r('app.media.computer2'))
    18. .height(220)
    19. .width('100%')
    20. .margin({ top: 30 })
    21. Image($r('app.media.computer3'))
    22. .height(220)
    23. .width('100%')
    24. .margin({ top: 30 })
    25. Image($r('app.media.computer4'))
    26. .height(220)
    27. .width('100%')
    28. .margin({ top: 30 })
    29. Image($r('app.media.computer5'))
    30. .height(220)
    31. .width('100%')
    32. .margin({ top: 30 })
    33. Image($r('app.media.computer6'))
    34. .height(220)
    35. .width('100%')
    36. .margin({ top: 30 })
    37. }
    38. .width('100%')
    39. .flexGrow(1)
    40. }
    41. .scrollable(ScrollDirection.Vertical)
    42. DetailBottom()
    43. }
    44. .height('90%')
    45. .width('100%')
    46. }
    47. }

    其中顶部DetailTop组件效果图如下:

    代码如下:

    1. @Component
    2. struct DetailTop {
    3. build() {
    4. Column() {
    5. Row() {
    6. Image($r('app.media.icon_return'))
    7. .height(40)
    8. .width(40)
    9. .margin({left: 20})
    10. .onClick(() => {
    11. router.push({
    12. uri: "pages/HomePage"
    13. })
    14. })
    15. }
    16. .width('100%')
    17. .height(35)
    18. .backgroundColor('#FF87CEEB')
    19. }
    20. .width('100%')
    21. .height(40)
    22. }
    23. }
  3. SwiperTop组件效果图如下:

    代码如下:

    1. @Component
    2. struct SwiperTop {
    3. build() {
    4. Column() {
    5. Swiper() {
    6. Image($r('app.media.computer1'))
    7. .height(220)
    8. .width('100%')
    9. Image($r('app.media.computer2'))
    10. .height(220)
    11. .width('100%')
    12. Image($r('app.media.computer3'))
    13. .height(220)
    14. .width('100%')
    15. Image($r('app.media.computer4'))
    16. .height(220)
    17. .width('100%')
    18. Image($r('app.media.computer5'))
    19. .height(220)
    20. .width('100%')
    21. Image($r('app.media.computer6'))
    22. .height(220)
    23. .width('100%')
    24. }
    25. .index(0)
    26. .autoPlay(true)
    27. .interval(3000)
    28. .indicator(true)
    29. .loop(true)
    30. .height(250)
    31. .width('100%')
    32. }
    33. .height(250)
    34. .width('100%')
    35. }
    36. }
  4. DetailText组件效果图如下:

    代码如下:

    1. @Component
    2. struct DetailText {
    3. build() {
    4. Column() {
    5. Row() {
    6. Image($r('app.media.icon_promotion'))
    7. .objectFit(ImageFit.Contain)
    8. .height(30)
    9. .width(30)
    10. .margin({ left: 10 })
    11. Text('Special Offer: ¥9999')
    12. .fontColor(Color.White)
    13. .fontSize(20)
    14. .margin({ left: 10 })
    15. }
    16. .width('100%')
    17. .height(35)
    18. .backgroundColor(Color.Red)
    19. Column() {
    20. Text('New Arrival: HUAWEI MateBook X Pro 2021')
    21. .fontSize(18)
    22. .margin({ left: 10 })
    23. .alignSelf(ItemAlign.Start)
    24. 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
    25. Collaboration, Emerald Green')
    26. .fontSize(14)
    27. .margin({ left: 10 })
    28. Row() {
    29. Image($r('app.media.icon_buy'))
    30. .objectFit(ImageFit.Contain)
    31. .height(30)
    32. .width(30)
    33. .margin({ left: 10 })
    34. Text('Limited offer')
    35. .fontSize(15)
    36. .fontColor(Color.Red)
    37. .margin({ left: 100 })
    38. }
    39. .backgroundColor(Color.Pink)
    40. .width('100%')
    41. .height(45)
    42. .margin({ top: 10 })
    43. Text(' Shipment: 2-day shipping')
    44. .fontSize(13)
    45. .fontColor(Color.Red)
    46. .margin({ left: 10, top: 5 })
    47. .alignSelf(ItemAlign.Start)
    48. Text(' Ship To: Hubei,Wuhan,China')
    49. .fontSize(13)
    50. .fontColor(Color.Red)
    51. .margin({ left: 10, top: 5 })
    52. .alignSelf(ItemAlign.Start)
    53. .onClick(() => {
    54. prompt.showDialog({ title: 'select address', })
    55. })
    56. Text('Guarantee: Genuine guaranteed')
    57. .fontSize(13)
    58. .margin({ left: 10, top: 5 })
    59. .alignSelf(ItemAlign.Start)
    60. }
    61. .height(170)
    62. .width('100%')
    63. }
    64. .height(180)
    65. .width('100%')
    66. }
    67. }

    DetailArsList组件效果图如下:

    代码如下:

    1. @Component
    2. struct DetailArsList{
    3. private arsItems: ArsData[]
    4. build() {
    5. Scroll() {
    6. Column() {
    7. List() {
    8. ForEach(this.arsItems, item => {
    9. ListItem() {
    10. ArsListItem({ arsItem: item })
    11. }
    12. }, item => item.id.toString())
    13. }
    14. .height('100%')
    15. .width('100%')
    16. .margin({ top: 5 })
    17. .listDirection(Axis.Vertical)
    18. }
    19. .height(200)
    20. }
    21. }
    22. }

    ArsListItem组件代码如下:

    1. @Component
    2. struct ArsListItem {
    3. private arsItem: ArsData
    4. build() {
    5. Row() {
    6. Text(this.arsItem.title + " :")
    7. .fontSize(11)
    8. .margin({ left: 20 })
    9. .flexGrow(1)
    10. Text(this.arsItem.content)
    11. .fontSize(11)
    12. .margin({ right: 20 })
    13. }
    14. .height(14)
    15. .width('100%')
    16. .backgroundColor(Color.White)
    17. }
    18. }
  5. DetailBottom组件效果图如下:

    代码如下:

    1. @Component
    2. struct DetailBottom {
    3. @Provide
    4. private value: number= 1
    5. dialogController: CustomDialogController = new CustomDialogController({
    6. builder: DialogExample({ action: this.onAccept }),
    7. cancel: this.existApp,
    8. autoCancel: true
    9. });
    10. onAccept() {
    11. }
    12. existApp() {
    13. }
    14. build() {
    15. Column() {
    16. Text('Buy')
    17. .width(40)
    18. .height(25)
    19. .fontSize(20)
    20. .fontColor(Color.White)
    21. .onClick(() => {
    22. this.value = 1
    23. this.dialogController.open()
    24. })
    25. }
    26. .alignItems(HorizontalAlign.Center)
    27. .backgroundColor(Color.Red)
    28. .width('100%')
    29. .height('10%')
    30. }
    31. }

    DialogExample自定义弹窗组件效果图如下:

    代码如下:

    1. @CustomDialog
    2. struct DialogExample {
    3. @Consume
    4. private value: number
    5. controller: CustomDialogController;
    6. action: () => void;
    7. build() {
    8. Column() {
    9. Progress({ value: this.value++ >= 100 ? 100 : this.value, total: 100, style: ProgressStyle.Capsule })
    10. .height(50)
    11. .width(100)
    12. .margin({ top: 5 })
    13. }
    14. .height(60)
    15. .width(100)
    16. }
    17. }

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料

 获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

 有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/757308
推荐阅读
相关标签
  

闽ICP备14008679号