1.引言
本文演示如果用HarmonyOS的ArkUI来开发一个购物应用程序。随着智能设备的快速发展,鸿蒙OS作为一种全场景分布式操作系统,已经在各种终端设备上取得了广泛的应用。为了更好地支持鸿蒙生态系统的发展,本人计划开发一个鸿蒙商城项目,旨在提供一个集成、多样化的平台,为用户提供便捷、安全、高效的购物体验。
2.项目背景
随着智能家居、智能穿戴、智能汽车等智能设备的普及,用户在不同场景使用不同设备进行购物的需求逐渐增加。鸿蒙商城将为用户提供一个统一的购物平台,实现多设备的融合使用。鸿蒙OS作为一个开放的生态系统,吸引了众多开发者和厂商加入。为了推动鸿蒙生态系统的健康发展,本人计划创建一个专属的商城,以展示和推广各类优秀的鸿蒙应用和产品。
3.项目框架
本项目实现的主要功能有:
- 登录
- 注册
- 主页
- 更新数据
- 查看商品详情
- 个人信息
首先,我们新建项目,选择空模板就行了,创建完是这个样子的
为了方便使用,我们先新建一个常量的文件,用来存放一些常量,例如一些文字,大小等
主要代码:
//各种默认值
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)
主要代码:
//登录界面
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)
主要代码:
//注册界面
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)主页
主要代码:
为了使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%')
}
}
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(查找功能):
//搜索界面
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)商品详情页面
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)个人页面
为了使页面更加美观,因此我们手动为它设计一个输入框
主要代码:
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实现的,还有很大的不足和需要改进的地方。鸿蒙系统作为我们第一个国产操作系统,其发展的艰辛可想而知,国产操作系统这条路任重而道远,希望有更多的同学能投入到这里面来,为国产操作系统贡献自己的一份力量。