1.引言

  本文演示如果用HarmonyOS的ArkUI来开发一个购物应用程序。随着智能设备的快速发展,鸿蒙OS作为一种全场景分布式操作系统,已经在各种终端设备上取得了广泛的应用。为了更好地支持鸿蒙生态系统的发展,本人计划开发一个鸿蒙商城项目,旨在提供一个集成、多样化的平台,为用户提供便捷、安全、高效的购物体验。

2.项目背景

 随着智能家居、智能穿戴、智能汽车等智能设备的普及,用户在不同场景使用不同设备进行购物的需求逐渐增加。鸿蒙商城将为用户提供一个统一的购物平台,实现多设备的融合使用。鸿蒙OS作为一个开放的生态系统,吸引了众多开发者和厂商加入。为了推动鸿蒙生态系统的健康发展,本人计划创建一个专属的商城,以展示和推广各类优秀的鸿蒙应用和产品。

3.项目框架

『江鸟中原』鸿蒙商城应用_Text

本项目实现的主要功能有:

  1. 登录
  2. 注册
  3. 主页
  4. 更新数据
  5. 查看商品详情
  6. 个人信息

首先,我们新建项目,选择空模板就行了,创建完是这个样子的

『江鸟中原』鸿蒙商城应用_Text_02

为了方便使用,我们先新建一个常量的文件,用来存放一些常量,例如一些文字,大小等

『江鸟中原』鸿蒙商城应用_输入框_03

主要代码:

//各种默认值
export default class Constant{
  //登陆标题大小
  static readonly LOGIN_SIZE: number = 40
  //登陆标题颜色
  static readonly LOGIN_COLOR: string = '#007DFF'
  //输入框长度
  static readonly INPUT_WIDTH: number = 300
  //输入框高度
  static readonly INPUT_HEIGHT: number = 60
  //按钮宽度
  static readonly BUTTON_WIDTH: number = 150
  //按钮高度
  static readonly BUTTON_HEIGHT: number = 50
  //登陆按钮颜色
  static readonly BUTTON_COLOR: string = '#6E34B8'
  //
  static readonly SPACE_SIZE: number = 5
  //标题大小
  static readonly TITLE_SIZE: number = 40
  //新鲜状态颜色
  static readonly FRESH_COLOR:string = '#41BA41'
  //过期状态颜色
  static readonly OVERDUE_COLOR:string = '#E62E31'
  //
  static readonly INPUT_IMAGE_SIZE:number = 60
  //
  static readonly AVATAR_SIZE:number = 50
}

(1)登陆页面

我现在需要添加一个登录页(Login)

『江鸟中原』鸿蒙商城应用_Text_04

主要代码:

//登录界面
import Constant from '../common/Constant'
import router from '@ohos.router'
@Entry
@Component
struct Login{
  @State message:string ='鸿蒙商城'
  @State username:string =''
  @State password:string =''

  build(){
    Row(){
      Column() {
        Image($r('app.media.icon'))
          .width(100)//宽度
          .height(100)//高度
          .borderRadius(10)//边框圆角
          .interpolation(ImageInterpolation.High)//图片插值
        Text(this.message)
          .fontColor(Constant.LOGIN_COLOR)
          .fontSize(Constant.LOGIN_SIZE)
          .fontWeight(FontWeight.Bold)
        TextInput({placeholder:'用户名'})
          .margin({top:20 })
          .width(Constant.INPUT_WIDTH)
          .height(Constant.INPUT_HEIGHT)
          .onChange((value:string)=>{
          this.username = value
          })
        TextInput({placeholder:'密码'}).type(InputType.Password)
          .margin({top:20 })
          .width(Constant.INPUT_WIDTH)
          .height(Constant.INPUT_HEIGHT)
          .onChange((value:string)=>{
            this.username = value
          })
        Button('登录')
          .width(Constant.INPUT_WIDTH)
          .height(Constant.INPUT_HEIGHT)
          .margin({top:30 })
          .backgroundColor('#6E34B8')
          .onClick(()=>{
            router.pushUrl({
              url:'pages/Index',
              params: {
                username: this.username,
                password: this.password
              }
            })
          })
        Flex(){
          Text('还未注册,前往注册。')
          Text('现在马上去')
            .fontColor(Constant.LOGIN_COLOR)
            .onClick(()=>{
              router.pushUrl({
                url:'pages/Register'
              })
            })
        }
        .margin(30)
      }
      .width('100%')
    }
    .height('100%')
  }
}

(2)注册页面

我现在需要添加一个注册页(Register)

『江鸟中原』鸿蒙商城应用_Text_05

主要代码:

//注册界面
import router from '@ohos.router'
import Constant from '../common/Constant'

@Entry
@Component
struct Register {
  @State message: string = '注册界面'
  @State username: string = ''
  @State password: string = ''
  @State email: string = ''

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontColor(Constant.LOGIN_COLOR)
          .fontSize(Constant.LOGIN_SIZE)
          .fontWeight(FontWeight.Bold)
        TextInput({ placeholder: '用户名' })
          .margin({ top: 20 })
          .width(Constant.INPUT_WIDTH)
          .height(Constant.INPUT_HEIGHT)
          .onChange((value: string) => {
            this.username = value
          })
        TextInput({ placeholder: '邮箱' })
          .margin({ top: 20 })
          .width(Constant.INPUT_WIDTH)
          .height(Constant.INPUT_HEIGHT)
          .onChange((value: string) => {
            this.email = value
          })
        TextInput({ placeholder: '密码' })
          .type(InputType.Password)
          .margin({ top: 20 })
          .width(Constant.INPUT_WIDTH)
          .height(Constant.INPUT_HEIGHT)
          .onChange((value: string) => {
            this.password = value
          })
        Button('注册')
          .width(Constant.BUTTON_WIDTH)
          .height(Constant.BUTTON_HEIGHT)
          .margin({ top: 30 })
          .backgroundColor(Constant.BUTTON_COLOR)
          .onClick(() => {
            router.pushUrl({
              url: 'pages/Login',
              params: {
                username: this.username,
                password: this.password,
                email: this.email
              }
            })
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

(3)主页

『江鸟中原』鸿蒙商城应用_Text_06

主要代码:

为了使Index干净一些,所以需要封装一下,将各种功能放到不同的包内

Index:

import router from '@ohos.router'
import TabBar from '../views/TabBar'
@Entry
@Component
struct Index{
  @State message:string = '主页'
  @State paramsFromIndex: object = router.getParams()
  build(){
    Row(){
      Column(){
        TabBar()
      }
      .width('100%')
    }
    .height('100%')
  }
}

『江鸟中原』鸿蒙商城应用_List_07

TabBar(导航):

//界面分类
import Home from './Home'
import Detailpage from'./Detailpage'
import Mine from './Mine'
@Component
export default struct TabBar{
  build(){
    Tabs({barPosition:BarPosition.End }){
    TabContent(){
      Home()
    }.tabBar(new BottomTabBarStyle($r('app.media.home'),'主页'))

    TabContent(){
      Detailpage()
    }.tabBar(new BottomTabBarStyle($r('app.media.data'),'商品详情'))

    TabContent(){
      Column().width('100%').height('100%').backgroundColor (Color.Green)
    }.tabBar(new BottomTabBarStyle($r('app.media.add'),'更新'))

    TabContent(){
      Mine()
    }.tabBar(new BottomTabBarStyle($r('app.media.me'),'我的'))
  }
  .vertical(false)
  .scrollable(true)
  .barMode(BarMode.Fixed)
  .onChange((index:number)=>{
    console.info(index.toString())
  })
  .width('100%')
  .backgroundColor(0xF1F3F5)
  }

}

Home(主界面):

//主界面
import Constant from '../common/Constant'
import SearchItem from './Search'
import ProductList from './ProductList'
@Preview
@Component
export default struct Home{
  @State isRefreshing:boolean = false

  build() {
    Column({space: Constant.SPACE_SIZE}){
      Row() {
        SearchItem()
      }
    Refresh({refreshing:$$this.isRefreshing,offset:10,friction:50}){
      Text('全部商品列表')
        .fontColor(Constant.LOGIN_COLOR)
        .fontSize(Constant.TITLE_SIZE)
        .fontWeight(FontWeight.Bold)
    }
      ProductList()
    }

    .backgroundColor(0xDCDCDC)
    .padding({top: 20})
      .width('100%')
      .height('100%')
    }
}

Search(查找功能):

『江鸟中原』鸿蒙商城应用_输入框_08

//搜索界面
import Constant from'../common/Constant'
@Component
export default struct SearchItem {
  @State search: string = ''

  build() {
    Row() {
      TextInput({ text: this.search, placeholder: '搜索' })
        .placeholderColor(Color.Grey)
        .placeholderFont({ size: 14, weight: 400 })
        .caretColor(Color.Blue)
        .width(250)
        .height(40)
        .margin({ top: 20, left: 10, right: 10 })
        .fontSize(14)
        .fontColor(Color.Black)
        .onChange((valve: string) => {
          this.search = valve
        })
      Button('搜索')
        .margin({ top: 20 })
        .fontSize(14)
        .height(40)
        .fontWeight(400)
        .width(60)
        .backgroundColor(Constant.BUTTON_COLOR)
        .onClick(() => {
          console.log('搜索' + this.search)
        })
    }
  }
}

(4)商品详情页面

『江鸟中原』鸿蒙商城应用_Text_09

Detailpage(详情页面):


import Constant from '../common/Constant'
import ProductList from './ProductList'
@Preview
@Component
export default struct Detailpage{
  @State isRefreshing:boolean = false

  build() {
    Column({space: Constant.SPACE_SIZE}){
      Row() {
        Refresh({refreshing:$$this.isRefreshing,offset:10,friction:50}){
          Text('商品列表')
            .fontColor(Constant.LOGIN_COLOR)
            .fontSize(Constant.TITLE_SIZE)
            .fontWeight(FontWeight.Bold)
        }
      }
      ProductList()
    }
    .backgroundColor(0xDCDCDC)
    .padding({top: 20})
    .width('100%')
    .height('100%')
  }
}

ProductList(商品列表):

//产品列表
import Constant from '../common/Constant'
import { ProductData, productList } from '../viewModel/ProductData'
@Component
export default struct ProductList {
  @State data:ProductData[] = productList
  build() {
    List({ space: Constant.SPACE_SIZE, initialIndex: 0 }) {
      ForEach(this.data, (item:ProductData) => {
        ListItem() {
          Row({ space: 20 }) {
            Column() {
              Image(item?.productImg)
                .width(50)
                .height(50)
            }
            .backgroundColor('#F1F5F9')
            .borderRadius(50)

            Column() {
              Text(item?.productName)
                .fontWeight(FontWeight.Bold)
                .fontSize(20)
              Text(`购买日期:` + item?.productDate + `|` + `数量:` + item?.productNum)
                .fontSize(14)
            }

            Column() {
              if(item?.productStatus == '过期') {
                Button(item?.productStatus)
                  .width(50)
                  .height(20)
                  .fontSize(9)
                  .fontColor(Color.Black)
                  .margin({ left: 10 })
                  .backgroundColor(Constant.OVERDUE_COLOR)
              }
                else{
                  Button(item?.productStatus)
                    .width(50)
                    .height (20)
                    .fontSize(9)
                    .fontColor(Color.Black)
                    .margin({left:10 })
                    .backgroundColor(Constant.FRESH_COLOR)
                }

            }
          }
        }
      })
    }
  }
}


(5)个人页面

『江鸟中原』鸿蒙商城应用_Text_10

为了使页面更加美观,因此我们手动为它设计一个输入框

主要代码:

TextPro(输入框):

import Constant from '../common/Constant'
@Component
export default struct TextPro {
  private inputImage?: Resource;
  private hintText?: string;

  build() {
    Row() {
      Image(this.inputImage !== undefined ? this.inputImage : '')
        .width(Constant.INPUT_IMAGE_SIZE)
        .height(Constant.INPUT_IMAGE_SIZE)
        .margin({ left: 12 })
      TextInput({ placeholder: this.hintText })
        .fontSize(16)
        .padding({ left: 16 })
        .placeholderColor('#99000000')
        .backgroundColor(Color.White)
        .fontWeight(FontWeight.Normal)
        .fontStyle(FontStyle.Normal)
        .fontColor(Color.Black)
        .margin({ right: 32 })
        .layoutWeight(1)
        .height(48)
    }
    .margin({ top: 24 })
    .borderRadius(24)
    .backgroundColor(Color.White)
    .width('93.3%')
    .height(64)
  }
}

Mine:

import Constant from '../common/Constant'
import TextPro from './TextPro'
@Preview
@Component
export default struct Mine {
  @State msg: string = '这是Mine'

  build() {
    Column() {
      Image($r('app.media.me'))
        .width(Constant.AVATAR_SIZE)
        .height(Constant.AVATAR_SIZE)
        .alignSelf(ItemAlign.Center)
      Text('个人信息')
        .fontColor(Constant.LOGIN_COLOR)
        .fontSize(16)
        .margin({ top: 10 })
        .alignSelf(ItemAlign.Center)
      TextPro({
        inputImage: $r('app.media.me'),
        hintText: '昵称'
      })
      TextPro({
        inputImage: $r('app.media.me'),
        hintText: '个性签名'
      })
    }
  }
}

4.项目总结

 本项目还只是处于开发的初级阶段,主要还是用ArkUI实现的,还有很大的不足和需要改进的地方。鸿蒙系统作为我们第一个国产操作系统,其发展的艰辛可想而知,国产操作系统这条路任重而道远,希望有更多的同学能投入到这里面来,为国产操作系统贡献自己的一份力量。