一、闹钟案例实操文档
1、创建目录
首先,在Pages下创建一个新的目录,命名为XPP,在目录下创建ArkTS,命名为Jishiqi
2、设置整体布局,使用Column垂直布局,设置高度和宽度,高度为百分之百,宽度为百分之九十。
@Component
export struct JishiqiPage {
build() {
Column() {
}.height('100%').width('90%')
}
}
使用row水平布局,设置图片的宽度和高度,给组件绑定菜单,点击后弹出菜单。
Row() {
Image($r('app.media.gengduo')).width(20).height(40)
.bindMenu(this.Gengduo())
}.margin({ left: 300,top:35})
2.1使用@Bulider装饰器,自定义构建函数,定义Gengduo
设置Flex弹性方式布局子组件的容器组件,设置弹性方向的布局和对齐方式,使用Column布局,垂直排列,高度设为100。Flex宽度设为150。
//设置的菜单
@Builder Gengduo() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
//FlexDirection.Column弹性方向为垂直布局,FlexAlign.Start对齐方式为开始反向
Column() {
}.height(100)
}.width(150)
}
2.2设置菜单内容
使用Row水平布局,设置宽度(width)为百分之九十,对齐方式为开始对齐,设置onclick点击事件,Divider设置分割线。
Row() {
Text('编辑').fontSize(25)
}
.width('90%')
.height(45)
.justifyContent(FlexAlign.Start)
.align(Alignment.Center)
.onClick(() => {
console.log('成功')
})
Divider()
Row() {
Text('设置').fontSize(25)
}
.width('90%')
.height(40)
.justifyContent(FlexAlign.Start)
.align(Alignment.Center)
.onClick(() => {
console.log('成功')
})
设置一个大的Column垂直布局,设置背景颜色,高度设置为百分之百,宽度设置为百分之九十。
build() {
Column() {
Row() {
Image($r('app.media.gengduo')).width(20).height(40)
.bindMenu(this.Gengduo())
}.margin({ left: 300,top:35})
}.height('100%').width('90%')
}
效果图如下所示:
3、设置时间选择组件
根据指定参数创建选择器,支持选择小时及分钟,TimePicker默认以24小时区间创建滑动选择器。onChange设置选择时间时触发事件。
TimePicker({
selected: this.selectedTime,
})
.useMilitaryTime(this.isMilitaryTime) //展示时间是否为24小时制
.onChange((value: TimePickerResult) => {
this.selectedTime.setHours(value.hour, value.minute)
console.info('select current date is: ' + JSON.stringify(value))
})
效果图如下所示:
4、使用row水平布局
使用row水平布局,设置text文本的外边距margin和Flex主轴方向均匀分配弹性元素,相邻子组件之间距离相同。第一个子组件和最后一个子组件与父元素边沿对齐。
Row(){
Text('常用计时器')
Text('添加')
}.width('90%')
.margin({top:40})
.justifyContent(FlexAlign.SpaceBetween)
效果图如下所示:
5、设置卡片样式
给卡片设置背景颜色,圆角以及内边框等。
//设置card()的样式 统一的卡片样式
@Styles function card() {
.width("95%")
.backgroundColor(Color.White)
.borderRadius(15)
.padding(20)
.margin(10)
.shadow({ radius: 6, color: "#1F000000", offsetX: 2, offsetY: 4 }) //阴影
}
5.1定义一个类
定义一个类,类型为string类型
class Sy{
name:string
time:string
constructor(name:string,time:string) {
this.name = name
this.time = time
}
}
5.2设置@State装饰器
设置@State装饰变量,和自定义组件渲染绑定起来。
@State sy:Array<Sy>= [
new Sy('刷牙','00:02:00'),
new Sy('面膜','00:20:00'),
new Sy('站立','00:12:00'),
new Sy('泡脚','00:30:00'),
new Sy('计时','00:20:00'),
new Sy('锻炼','00:50:00'),
new Sy('吃饭','00:25:00'),
new Sy('化妆','00:50:00'),
new Sy('吃饭','00:25:00'),
new Sy('化妆','00:50:00'),
]
利用List列表循环,ForEach循环渲染,使代码简洁化,设置权重。
List(){
ForEach(this.sy,(item:Sy)=>{
ListItem(){
Row(){
Text(item.name)
Text(item.time)
}.justifyContent(FlexAlign.SpaceBetween)
.width('95%').height(80)
.card()
.borderWidth(1).backgroundColor(Color.White)
}
})
}.layoutWeight(1)
6、设置自定义弹窗
通过CustomDialogController类显示自定义弹窗,builder设置自定义弹窗内容构造器,cancel设置点击遮障层退时的回调,alignment可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示。
//自定义弹窗
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
cancel: this.onCancel,
confirm: this.onAccept,
}),
alignment: DialogAlignment.Bottom,// 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示
customStyle:true,
})
onCancel() {
console.info('Callback when the first button is clicked')
}
onAccept() {
console.info('Callback when the second button is clicked')
}
Image($r('app.media.tingzhi')).width(60).height(60)
.onClick(()=>{
this.dialogController.open()
})
效果图如下:
7、设置动态弹窗
//动态中的弹窗
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
cancel: () => void
confirm: () => void
}
7.1使用@Bulider装饰器,自定义构建函数,定义Gengduo
菜单设置Flex弹性方式布局子组件的容器组件,设置弹性方向的布局和对齐方式,使用Column布局,垂直排列,高度设为50,Flex宽度设为100。
//设置的菜单
@Builder Gengduo() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Column() {
Row() {
Text('设置').fontSize(25).margin({bottom:-20})
}
.width('90%')
.height(25)
.justifyContent(FlexAlign.Center)
.onClick(() => {
console.log('成功')
})
}.height(50)
}.width(100)
}
设置一个大的Column,设置背景颜色,高度和宽度分别为百分之百
Image($r('app.media.gengduo'))
.width(50)
.margin({ left: 300,top:35})
.bindMenu(this.Gengduo())
效果图如下所示:
7.2设置计时器
使用Column垂直布局,嵌套Stack层叠,TextTimer通过文本显示计时信息并控制计时器状态的组件,TextTimerController控制文本计时器,进行计时,isCountDown判断是否倒计时,为true开始倒计时,count设置倒计时的时间。
textTimerController: TextTimerController = new TextTimerController()
@State format: string = 'mm:ss.SS'
build() {
Column(){
Stack(){
Image($r('app.media.jishi1'))
.backgroundImage('#CCCCCC')
.width('85%')
.height('40%')
TextTimer({ isCountDown: true, count: 3000000, controller: this.textTimerController })
.format(this.format)
.fontColor(Color.Black)
.fontSize(50)
.onTimer((utc: number, elapsedTime: number) => {
console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
})
}
}.margin({top:-5})
}
效果图如下所示:
8、设置取消和开始图片
给取消图片设置点击取消事件,暂停图片设置点击开始,TextTimerController控制文本计时器,进行计时。
Row() {
Image($r('app.media.quxiao')).width(80).height(80)
.onClick(() => {
this.controller.close()
this.cancel()
})
Image($r('app.media.zanting')).width(67).height(67)
.onClick(() => {
this.textTimerController.start()
})
}.width('90%')
.height(500)
.justifyContent(FlexAlign.SpaceAround)
效果图如下所示:
9、主页面代码内容如下所示:
//设置card()的样式 统一的卡片样式
@Styles function card() {
.width("95%")
.backgroundColor(Color.White)
.borderRadius(15)
.padding(20)
.margin(10)
.shadow({ radius: 6, color: "#1F000000", offsetX: 2, offsetY: 4 }) //阴影
}
class Sy{
name:string
time:string
constructor(name:string,time:string) {
this.name = name
this.time = time
}
}
@Component
export struct JishiqiPage {
@State isMilitaryTime: boolean = false
private selectedTime: Date = new Date('2024-06-6T08:00:00')
//设置的菜单
@Builder Gengduo() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
//FlexDirection.Column弹性方向为垂直布局,FlexAlign.Start对齐方式为开始反向
Column() {
Row() {
Text('编辑').fontSize(25)
}
.width('90%')
.height(45)
.justifyContent(FlexAlign.Start)
.align(Alignment.Center)
.onClick(() => {
console.log('成功')
})
Divider()
Row() {
Text('设置').fontSize(25)
}
.width('90%')
.height(40)
.justifyContent(FlexAlign.Start)
.align(Alignment.Center)
.onClick(() => {
console.log('成功')
})
}.height(100)
}.width(150)
}
@State sy:Array<Sy>= [
new Sy('刷牙','00:02:00'),
new Sy('面膜','00:20:00'),
new Sy('站立','00:12:00'),
new Sy('泡脚','00:30:00'),
new Sy('计时','00:20:00'),
new Sy('锻炼','00:50:00'),
new Sy('吃饭','00:25:00'),
new Sy('化妆','00:50:00'),
new Sy('吃饭','00:25:00'),
new Sy('化妆','00:50:00'),
]
//自定义弹窗
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
cancel: this.onCancel,
confirm: this.onAccept,
}),
alignment: DialogAlignment.Bottom,// 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示
customStyle:true,
})
onCancel() {
console.info('Callback when the first button is clicked')
}
onAccept() {
console.info('Callback when the second button is clicked')
}
build() {
Column() {
Row() {
Image($r('app.media.gengduo')).width(20).height(40)
.bindMenu(this.Gengduo())
}.margin({ left: 300,top:35})
TimePicker({
selected: this.selectedTime,
})
.useMilitaryTime(this.isMilitaryTime) //展示时间是否为24小时制
.onChange((value: TimePickerResult) => {
this.selectedTime.setHours(value.hour, value.minute)
console.info('select current date is: ' + JSON.stringify(value))
})
Row(){
Text('常用计时器')
Text('添加')
}.width('90%')
.margin({top:40})
.justifyContent(FlexAlign.SpaceBetween)
List(){
ForEach(this.sy,(item:Sy)=>{
ListItem(){
Row(){
Text(item.name)
Text(item.time)
}.justifyContent(FlexAlign.SpaceBetween)
.width('95%').height(80)
.card()
.borderWidth(1).backgroundColor(Color.White)
}
})
}.layoutWeight(1)
Image($r('app.media.tingzhi')).width(60).height(60)
.onClick(()=>{
this.dialogController.open()
})
}.height('100%').width('90%')
}
}
9.1主页面效果图如下所示:
10、弹窗页面内容代码如下所示:
//动态中的弹窗
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
cancel: () => void
confirm: () => void
//设置的菜单
@Builder Gengduo() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Column() {
Row() {
Text('设置').fontSize(25).margin({bottom:-20})
}
.width('90%')
.height(25)
.justifyContent(FlexAlign.Center)
.onClick(() => {
console.log('成功')
})
}.height(50)
}.width(100)
}
textTimerController: TextTimerController = new TextTimerController()
@State format: string = 'mm:ss.SS'
build() {
Column({ space: 15 }) {
Image($r('app.media.gengduo'))
.width(50)
.margin({ left: 300,top:35})
.bindMenu(this.Gengduo())
Column(){
Stack(){
Image($r('app.media.jishi1'))
.backgroundImage('#CCCCCC')
.width('85%')
.height('40%')
TextTimer({ isCountDown: true, count: 3000000, controller: this.textTimerController })
.format(this.format)
.fontColor(Color.Black)
.fontSize(50)
.onTimer((utc: number, elapsedTime: number) => {
console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
})
}
Row() {
Image($r('app.media.quxiao')).width(80).height(80)
.onClick(() => {
this.controller.close()
this.cancel()
})
Image($r('app.media.zanting')).width(67).height(67)
.onClick(() => {
this.textTimerController.start()
})
}.width('90%')
.height(500)
.justifyContent(FlexAlign.SpaceAround)
}.margin({top:-5})
}.backgroundColor('#F0F0F0').height('100%').width('100%')
}
}
10.1弹窗效果图如下所示:
11、整体完整代码如下:
//设置card()的样式 统一的卡片样式
@Styles function card() {
.width("95%")
.backgroundColor(Color.White)
.borderRadius(15)
.padding(20)
.margin(10)
.shadow({ radius: 6, color: "#1F000000", offsetX: 2, offsetY: 4 }) //阴影
}
class Sy{
name:string
time:string
constructor(name:string,time:string) {
this.name = name
this.time = time
}
}
@Component
export struct JishiqiPage {
@State isMilitaryTime: boolean = false
private selectedTime: Date = new Date('2024-06-6T08:00:00')
//设置的菜单
@Builder Gengduo() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
//FlexDirection.Column弹性方向为垂直布局,FlexAlign.Start对齐方式为开始反向
Column() {
Row() {
Text('编辑').fontSize(25)
}
.width('90%')
.height(45)
.justifyContent(FlexAlign.Start)
.align(Alignment.Center)
.onClick(() => {
console.log('成功')
})
Divider()
Row() {
Text('设置').fontSize(25)
}
.width('90%')
.height(40)
.justifyContent(FlexAlign.Start)
.align(Alignment.Center)
.onClick(() => {
console.log('成功')
})
}.height(100)
}.width(150)
}
@State sy:Array<Sy>= [
new Sy('刷牙','00:02:00'),
new Sy('面膜','00:20:00'),
new Sy('站立','00:12:00'),
new Sy('泡脚','00:30:00'),
new Sy('计时','00:20:00'),
new Sy('锻炼','00:50:00'),
new Sy('吃饭','00:25:00'),
new Sy('化妆','00:50:00'),
new Sy('吃饭','00:25:00'),
new Sy('化妆','00:50:00'),
]
//自定义弹窗
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
cancel: this.onCancel,
confirm: this.onAccept,
}),
alignment: DialogAlignment.Bottom,// 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示
customStyle:true,
})
onCancel() {
console.info('Callback when the first button is clicked')
}
onAccept() {
console.info('Callback when the second button is clicked')
}
build() {
Column() {
Row() {
Image($r('app.media.gengduo')).width(20).height(40)
.bindMenu(this.Gengduo())
}.margin({ left: 300,top:35})
TimePicker({
selected: this.selectedTime,
})
.useMilitaryTime(this.isMilitaryTime) //展示时间是否为24小时制
.onChange((value: TimePickerResult) => {
this.selectedTime.setHours(value.hour, value.minute)
console.info('select current date is: ' + JSON.stringify(value))
})
Row(){
Text('常用计时器')
Text('添加')
}.width('90%')
.margin({top:40})
.justifyContent(FlexAlign.SpaceBetween)
List(){
ForEach(this.sy,(item:Sy)=>{
ListItem(){
Row(){
Text(item.name)
Text(item.time)
}.justifyContent(FlexAlign.SpaceBetween)
.width('95%').height(80)
.card()
.borderWidth(1).backgroundColor(Color.White)
}
})
}.layoutWeight(1)
Image($r('app.media.tingzhi')).width(60).height(60)
.onClick(()=>{
this.dialogController.open()
})
}.height('100%').width('90%')
}
}
//动态中的弹窗
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
cancel: () => void
confirm: () => void
//设置的菜单
@Builder Gengduo() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
Column() {
Row() {
Text('设置').fontSize(25).margin({bottom:-20})
}
.width('90%')
.height(25)
.justifyContent(FlexAlign.Center)
.onClick(() => {
console.log('成功')
})
}.height(50)
}.width(100)
}
textTimerController: TextTimerController = new TextTimerController()
@State format: string = 'mm:ss.SS'
build() {
Column({ space: 15 }) {
Image($r('app.media.gengduo'))
.width(50)
.margin({ left: 300,top:35})
.bindMenu(this.Gengduo())
Column(){
Stack(){
Image($r('app.media.jishi1'))
.backgroundImage('#CCCCCC')
.width('85%')
.height('40%')
TextTimer({ isCountDown: true, count: 3000000, controller: this.textTimerController })
.format(this.format)
.fontColor(Color.Black)
.fontSize(50)
.onTimer((utc: number, elapsedTime: number) => {
console.info('textTimer notCountDown utc is:' + utc + ', elapsedTime: ' + elapsedTime)
})
}
Row() {
Image($r('app.media.quxiao')).width(80).height(80)
.onClick(() => {
this.controller.close()
this.cancel()
})
Image($r('app.media.zanting')).width(67).height(67)
.onClick(() => {
this.textTimerController.start()
})
}.width('90%')
.height(500)
.justifyContent(FlexAlign.SpaceAround)
}.margin({top:-5})
}.backgroundColor('#F0F0F0').height('100%').width('100%')
}
}