上~~期文章讲到,欢迎界面的功能实现已经基本完成,想必同学们也是迫不及待想看我的新内容了。在此,我再次劝说想学习新知识的同学,一定要远离我的文章。
接下来我们步入正题,从此次文章开始我们就要一步一步的去实现程序的主要功能了。
一、首页的页面转换设计
在图片中我们可以看到,整体呢是一个从上到下的页面布局,在页面的最下方的呢有一行导航栏,包括‘记录’、’发现‘和‘我的’这三栏,虽然说后两个我并不打算写,但是这基本的页面转换功能要有。在这我想出了两种方案,其一是利用页面的路由,在点击相应的触发源时进行页面跳转;其二就是使用Tabs组件,此方法更为简单实用,它可以实现页面内视图内容快速转换,还不存在堆栈中页面过多的问题。
下面就是对主页面的tabs组件的设计:
@Entry
@Component
struct Index {
@Builder TabBarBuilder(title: ResourceStr, image: ResourceStr, index: number) {
Column({ space: CommonConstants.SPACE_8 }) {
Image(image)
.width(22)
.fillColor(this.selectColor(index))
Text(title)
.fontSize(14)
.fontColor(this.selectColor(index))
}
}
selectColor(index: number) {
return this.currentIndex === index ? $r('app.color.primary_color') : $r('app.color.gray')
}
build() {
Tabs({ barPosition: BreakpointConstants.BAR_POSITION.getValue(this.currentBreakpoint) }) {
TabContent() {
RecordIndex({isPageShow: this.isPageShow})
}
.tabBar(this.TabBarBuilder($r('app.string.tab_record'), $r('app.media.ic_calendar'), 0))
TabContent() {
Text('发现页面')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_discover'), $r('app.media.discover'), 1))
TabContent() {
Text('我的主页')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_user'), $r('app.media.ic_user_portrait'), 2))
}
.width('100%')
.height('100%')
.onChange(index => this.currentIndex = index)
.vertical(new BreakpointType({
sm: false,
md: true,
lg: true
}).getValue(this.currentBreakpoint))
}
}
在其中存在了一个函数:
@Builder TabBarBuilder(title: ResourceStr, image: ResourceStr, index: number)
这是因为在TabContent下不能直接去设计内容的图片等,所以需要自定义一个布局的函数去调用。
二、首页的页面布局设计
根据文章中的图片,实现布局。以下是头部的搜索的代码:
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct SearchHeader {
build() {
Row({space: CommonConstants.SPACE_6}){
Search({placeholder: '搜索饮食或运动信息'})
.textFont({size: 18})
.layoutWeight(1)
Badge({count: 1, position: BadgePosition.RightTop, style: {fontSize: 12}}){
Image($r('app.media.ic_public_email'))
.width(24)
}
}
.width(CommonConstants.THOUSANDTH_940)
}
}
其中,badge是一个组件,用来在图片上显示提示信息,即角标,例如来消息之后软件的右上角会有一个数字;字段count是提示的数字,position是显示的样式位置,这里采用右上角,style就是其余的样式了,比如字体大小、字体颜色等。
下述是日期设置的设计代码:
//声明使用日期选择器
@StorageProp('selectedDate') selectedDate: number = DateUtil.beginTimeOfDay(new Date())
controller: CustomDialogController = new CustomDialogController({
builder: DatePickDialog({selectedDate: new Date(this.selectedDate)})
})
//build中的
Row(){
Text(DateUtil.formatDate(this.selectedDate))
.fontColor($r('app.color.secondary_color'))
Image($r('app.media.ic_public_spinner'))
.width(20)
.fillColor($r('app.color.secondary_color'))
}
.padding(CommonConstants.SPACE_8)
.onClick(() => this.controller.open())
在上述代码中,由dateutil的字样,这是在AppScope文件下定义的方法类,此处用的方法是为了获得开始日期的毫秒值;而且其中selectedDate变量使用@StorageProp来修饰,进行单向的参数修改。
根据对功能的分析,点击日期后会有日期选择的弹窗,以下是弹窗的代码:
import { CommonConstants } from '../../common/constants/CommonConstants'
@CustomDialog
export default struct DatePickDialog {
controller: CustomDialogController
selectedDate: Date = new Date()
build() {
Column({space: CommonConstants.SPACE_12}){
// 1.日期选择器
DatePicker({
start: new Date('2020-01-01'),
end: new Date(),
selected: this.selectedDate
})
.onChange((value: DatePickerResult) => {
this.selectedDate.setFullYear(value.year, value.month, value.day)
})
// 2.按钮
Row({space:CommonConstants.SPACE_12}){
Button('取消')
.width(120)
.backgroundColor($r('app.color.light_gray'))
.onClick(() => this.controller.close())
Button('确定')
.width(120)
.backgroundColor($r('app.color.primary_color'))
.onClick(() => {
// 1.保存日期到全局存储
AppStorage.SetOrCreate('selectedDate', this.selectedDate.getTime())
// 2.关闭窗口
this.controller.close()
})
}
}
.padding(CommonConstants.SPACE_12)
}
}
代码中将日期保存到全局时,是不能直接去调用保存日期格式,它是不能作为状态变量监控,所以我在这里将日期转换成了毫秒值进行储存,以便于在程序中便于其余界面使用此日期。
这期文章就写到这里,感觉这篇文章的代码工作量已经不少了,再写我脑子就要晕了,下期文章我将写完页面的布局和设计。