前言
hello 大家好 我是无言。最近在开发一个鸿蒙项目,刚好遇到了一个自定义比较强,样式还挺不错的日期选择器需求,经过不断调试打磨,最终效果还不错,所以打算分享出来,给大家一些创意灵感。
主要实现的功能
- 选中日期回传给父组件。
- 根据父组件默认选中时间打开子组件弹窗回显日期。
- 动态加载日期边滚动边加载后续数据提升性能。
实现效果先一睹为快。
实现过程
一、准备工作
- 安装好最新DevEco Studio 开发工具,创建一个新的空项目。
- 为了避免重复造轮子,所以时间处理工具我这里用了[dayjs]。
二、先把整个弹窗逻辑实现
- 创建弹窗子组件文件
ets/components/TimeDateDialog.ets
下面代码建议着重看下添加注释的地方,是容易踩坑的地方,所以我都特别标注出来了。
//弹窗具体内容
@CustomDialog
struct CustomDialogDate {
controller?: CustomDialogController
@State dateList:string[]=['2024-01-11','2024-01-12','2024-01-13','2024-01-14','2024-01-15'] //只存储天
@State hourList:string[]=['01','02','03','04','05'] //只存储小时
@State minList:string[]=['05','10','15','20','25'] //只存分钟
cancel: () => void = () => {
}
confirm: (data:string) => void = () => {
}
aboutToAppear(): void {
}
build() {
Column() {
Row(){
Text('显示时间').fontSize(18)
}.padding({ bottom:25 }).width('100%').justifyContent(FlexAlign.Center)
// 滚动选中区域
Flex(){
// 时间
Flex(){
// 时间
TextPicker({ range: this.dateList})
.width('50%')
.canLoop(false)//不循环
.divider({
strokeWidth: 1,
startMargin: 0,
endMargin: 0,
color:'#ececec'
})
.textStyle({color:'#777777', font: {size: 15, weight: 400}})
.selectedTextStyle({color: '#ffd96868', font: {size: 15, weight: 600}})
TextPicker({ range: this.hourList }).width('25%')
.divider({
strokeWidth: 1,
startMargin: 0,
endMargin: 0,
color:'#ececec'
})
.textStyle({color:'#777777', font: {size: 15, weight: 400}})
.selectedTextStyle({color: '#ffd96868', font: {size: 15, weight: 600}})
//分钟
TextPicker({ range: this.minList}).width('25%')
.divider({
strokeWidth: 1,
startMargin: 0,
endMargin: 0,
color:'#ececec'
})
.textStyle({color:'#777777', font: {size:15, weight: 400}})
.selectedTextStyle({color: '#ffd96868', font: {size: 15, weight: 600}})
}
}
// 按钮
Row(){
Button('取消', { type: ButtonType.Normal, stateEffect: true })
.margin({right:6})
.borderRadius(6)
.backgroundColor('#fff')
.fontColor('#ffd96868')
.borderWidth(1)
.borderColor('#ffd96868')
.fontSize(15)
.width(156)
.onClick(()=>{
this.controller?.close()
})
Button('确定', { type: ButtonType.Normal, stateEffect: true })
.margin({left:6})
.borderRadius(6)
.fontSize(15)
.backgroundColor('#ffd96868')
.width(156)
.onClick(()=>{
this.confirm('回传信息给父组件')
this.controller?.close()
})
}.justifyContent(FlexAlign.Center)
.padding({top:15})
.margin({top:25})
}.width('100%')
.padding(16)
.backgroundColor('#fff')
.borderRadius({topLeft:15,topRight:15})
}
}
//定义controller对象 主要作用父子通信 父组件调用子组件方法 唤醒弹窗
export class DialogDateController {
ShowDialog = (value?: string) => {
}
}
//弹窗控制逻辑
@Component
export struct TimeDateDialog { //修改命名 注意前面加了 export 需要暴露组件
private controller: DialogDateController = new DialogDateController();
CustomDialogController: CustomDialogController | null =null ;
@Prop defaultTime: string;
cancel?: () => void
confirm?: (data:string) => void = () => {
}
// 打开显示弹窗
private async