#打卡不停更#【木棉花】:基于ArkUI的运动记录Demo 原创
前言
在参加了"HarmonyOS ArkUI入门训练营——健康生活实战"后,了解并学习了声明式UI开发框架及组件用法,本文是对笔者结营作品中作一个小分享。在笔者上篇及前篇文章中,已对本demo作了部分组件的介绍,本文将对剩余部分作介绍分享~
概述
本文主要介绍的是搜索栏跳转至搜索结果界面,以及前述文章介绍的组件的应用。效果图如下:
正文
一、工程文件架构
二、完善主界面及数据的传递
1、数据传递实现运动记录的增删改查
由于运动记录的增删改查是在弹窗组件的点击事件里相应的,起初我是打算使用@Link来传递数据的,但是在自定义弹窗组件的builder里会对$修饰的变量报错,于是我就改用全局变量了。为了响应变量的状态变化,用@State装饰。也许用数据库会更方便些,后期再作优化吧~
var RDArray: Array<RecordData> = []
var RSports: Array<SportsData> = []
Record 弹窗下定义变量
@State RecordDataArray: Array<RecordData> = RDArray
@State RecordSports: Array<SportsData> = RSports
在上上篇文章提到的弹窗组件中,定义点击事件。“修改记录”模式下,“删除记录”按键的“确定”响应代码如下:
secondaryButton: {
value: '确定',
action: () => {
RDArray.splice(this.item_index, 1)
RSports.splice(this.item_index, 1)
this.controller.close()
}
主弹窗右上角的“确定”按键响应代码如下:
if (this.mode == 0) {
RDArray.push({
'name': this.sportsItem.name,
'image': this.sportsItem.image,
'time': this.time,
'sum': this.sum
})
RSports.push(this.sportsItem)
}
else if (this.mode == 1) {
RDArray[this.item_index]=
{
'name': this.sportsItem.name,
'image': this.sportsItem.image,
'time': this.time,
'sum': this.sum
}
RSports.push(this.sportsItem)
}
2、完善主页面
主页面底部是有两个页签的导航栏,第一个页签显示目录界面,该界面的顶部有一个搜索栏,与下方的目录成纵向布局,第二个页签显示记录界面。记录界面的组件与上篇文章提到的List组件用法无异,只是渲染的数据不同罢了,代码相似所以本文就不介绍了。此外对于记录界面,若无记录则显示“暂无记录”,为了让界面美观些,笔者给背景添加了图片。点击“搜索”按键时会带参跳转至搜索结果的页面’pages/search_result’,代码如下:
@Entry
@Component
struct SportsCategoryList {
@State RDArray: Array<RecordData> = RDArray
@State RSports: Array<SportsData> = RSports
@State currentIndex: number = 0;
@State search_item: string = '运动名称';
private sportsItem: SportsData[] = initializeOnStartup()
@Builder bottomBarBuilder(name: string, image_active: Resource, image_inactive: Resource, index: number) {
Column() {
Image(this.currentIndex === index ? image_active : image_inactive).width(32).aspectRatio(1).fillColor(this.currentIndex === index ? '#3ECF69' : '#bfbfbf')
Text(name).fontColor(this.currentIndex === index ? '#3ECF69' : '#bfbfbf').fontSize(18).margin({ bottom: 3 })
}.alignItems(HorizontalAlign.Center).width('100%')
}
build() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Column() {
Row() {
Image($r('app.media.search'))
.width(26)
.height(26)
.objectFit(ImageFit.Cover)
.margin({ left: 10 })
TextInput({ placeholder: '请输入运动名称' })
.width('60%')
.height(30)
.backgroundColor(Color.White)
.onChange((value: string) => {
this.search_item = value
})
Blank()
Button('搜索')
.backgroundColor('#3ECF69')
.borderRadius(30)
.fontSize(15)
.fontColor(Color.White)
.height(30)
.width('20%')
.margin({ left: 8, right: 3, top: 3, bottom: 3 })
.onClick(() => {
router.push({
url: 'pages/search_result',
params: {
sports: this.search_item
}
})
})
} //search
.borderColor('#3ECF69')
.borderWidth(2)
.borderRadius(50)
.backgroundColor(Color.White)
.width('90%')
.height(40)
.margin({ top: 5, bottom: 5, left: 5, right: 5 })
SportsCategory({ sportsItems: this.sportsItem ,RecordSports:$RSports,RecordDataArray:$RDArray})
}
.backgroundImage($r('app.media.background'))
.backgroundImageSize({ width: '100%', height: '100%' })
}.tabBar(this.bottomBarBuilder('主页', $r('app.media.index'), $r('app.media.indexgray'), 0))
TabContent() {
Column() {
if (this.RDArray.length != 0) {
RecordGrid({RecordDataArray:$RDArray,RecordSports:$RSports})
}
else {
Text('暂无运动记录').fontSize(19).width('100%').height(20).margin({ top: 12, left: 20 })
}
}
.width('100%')
.height('100%')
.backgroundImage($r('app.media.background2'))
.backgroundImageSize({ width: '100%', height: '100%' })
}.tabBar(this.bottomBarBuilder('记录', $r('app.media.statistics'), $r('app.media.statisticsgray'), 1))
}
.onChange((index: number) => {
this.currentIndex = index;
})
}
}
三、搜索结果界面
1、接收页面路由的传参,并初始化工程内的运动项数据,便于遍历查找。
import router from '@ohos.router';
import { initializeOnStartup } from '../model/SportsDataModels'
import { SportsData,RecordData } from '../model/SportsData'
import { SportsGrid,RDArray,RSports } from './SportsCategoryList'
@Entry
@Component
struct Search_result {
@State name:string = router.getParams()['sports']
private sportsItem: SportsData[] = initializeOnStartup()
private ResultDataArray: Array<SportsData> = []
...
}
由于有的运动项目名称相同,但配速不同,因此在设置字符串匹配判断时取字符串的子串来匹配。
aboutToAppear() {
let item;
for (item of this.sportsItem) {
if (item.name.length >= this.name.length) {
if (this.name == item.name.substring(0, this.name.length)) {
this.ResultDataArray.push(item);
}
}
else {
if (this.name == item.name) {
this.ResultDataArray.push(item);
}
}
}
}
将SportsCategoryList中的SportsGrid组件用export修饰,就能在搜索结果界面使用了,将搜索的结果用数组存放,接着传参进SportsGrid进行列表渲染。
build() {
Column() {
PageTitle({ title: '搜索结果' })
Row() {
Image($r('app.media.search'))
.width(26)
.height(26)
.objectFit(ImageFit.Cover)
.margin({ left: 10 })
TextInput({placeholder:'请输入运动名称'})
.width('60%')
.height(30)
.backgroundColor(Color.White)
Blank()
Button('搜索')
.backgroundColor('#3ECF69')
.borderRadius(30)
.fontSize(15)
.fontColor(Color.White)
.height(30)
.width('20%')
.margin({ left: 8, right: 3, top: 3, bottom: 3 })
.onClick(() => {
router.push({
url: 'pages/search_result',
params: {
sports: this.sportsItem
}
})
})
} //search
.borderColor('#3ECF69')
.borderWidth(2)
.borderRadius(50)
.backgroundColor(Color.White)
.width('90%')
.height(40)
.margin(5)
Scroll() {
Column() {
if (this.ResultDataArray.length != 0) {
SportsGrid({ sportsItems: this.ResultDataArray })
}
else {
Text('没有查到与此相关的结果').fontSize(19).width('100%').height(20).margin({ top: 12, left: 20 })
}
}
}
.scrollBar(BarState.Off)
}.height('100%')
.width('100%')
.backgroundImage($r('app.media.background'))
.backgroundImageSize({ width: '100%', height: '100%' })
}
}
@Component
struct PageTitle {
private title: string
build() {
Flex({ alignItems: ItemAlign.Start }) {
Image($r('app.media.Back'))
.width(21.8)
.height(19.6)
Text(this.title)
.fontSize(21.8)
.margin({ left: 17.4 })
}
.height(61)
.padding({ top: 15, bottom: 10, left: 28.3 })
.onClick(() => {
router.back()
})
}
结语
以上就是本次的小分享啦!❀❀
各个文件讲解用不同的颜色标出很赞
👍感谢支持