目录
案例效果
资源文件与初始化
string.json
color.json
CommonConstant
添加任务
首页组件
任务列表初始化
任务列表视图
任务编辑页
添加跳转
任务目标设置模型(formatParams)
编辑页面
详情页
任务编辑列表项
目标设置展示
引入目标设置
目标设置展示实现
TaskInfo 枚举模型设置
弹窗构造逻辑
定义单击事件
定义 BroadCast
定义弹窗视图
定义弹窗 builder 组件
目标设置弹窗实现
目标设置窗口逻辑
任务目标设置视图模型
频率设置视图模型
时间提醒弹窗实现
更新TaskDetail
实现编辑任务列表的开启提醒与提醒时间
实现时间提醒弹窗
频率弹窗和提交完成的实现
实现频率任务项视图
实现频率设置弹窗
定义频率设置视图模型
案例效果
资源文件与初始化
string.json
{
"string": [
{
"name": "entry_desc",
"value": "description"
},
{
"name": "entryAbility_desc",
"value": "description"
},
{
"name": "entryAbility_label",
"value": "List_HDC"
},
{
"name": "task_morning",
"value": "早起"
},
{
"name": "task_water",
"value": "喝水"
},
{
"name": "task_apple",
"value": "吃苹果"
},
{
"name": "task_smile",
"value": "每日微笑"
},
{
"name": "task_brush",
"value": "每日刷牙"
},
{
"name": "task_night",
"value": "早睡"
},
{
"name": "already_open",
"value": "已开启"
},
{
"name": "complete",
"value": "完成"
},
{
"name": "frequency",
"value": "频率"
},
{
"name": "remind_time",
"value": "提醒时间"
},
{
"name": "open_reminder",
"value": "开启提醒"
},
{
"name": "target_setting",
"value": "目标设置"
},
{
"name": "cancel",
"value": "取消"
},
{
"name": "confirm",
"value": "确认"
},
{
"name": "set_your_frequency",
"value": "请设置您的频率"
}
]
}
color.json
{
"color": [
{
"name": "white",
"value": "#FFFFFF"
},
{
"name": "primaryBgColor",
"value": "#F1F3F5"
},
{
"name": "titleColor",
"value": "#182431"
},
{
"name": "btnBgColor",
"value": "#F2F2F2"
},
{
"name": "statusTipColor",
"value": "#989A9C"
},
{
"name": "blueColor",
"value": "#007DFF"
},
{
"name": "black",
"value": "#000000"
},
{
"name": "primaryRed",
"value": "#E92F4F"
},
{
"name": "tabTitleColor",
"value": "#999"
},
{
"name": "signatureColor",
"value": "#66686a"
},
{
"name": "leveColor",
"value": "#c99411"
},
{
"name": "leveBgColor",
"value": "#d4e6f1"
},
{
"name": "borderColor",
"value": "#cccccc"
},
{
"name": "mineBgColor",
"value": "#edf2f5"
},
{
"name": "launcherBlueColor",
"value": "#4694C2"
},
{
"name": "disabledColor",
"value": "#dddadc"
}
]
}
CommonConstant
// ets/common/contants/CommonConstant.ets
export const THOUSANDTH_80: string = '8%'
export const THOUSANDTH_100: string = '10%'
export const THOUSANDTH_400: string = '40%'
export const THOUSANDTH_500: string = '50%'
export const THOUSANDTH_560: string = '56%'
export const THOUSANDTH_800: string = '80%'
export const THOUSANDTH_900: string = '90%'
export const THOUSANDTH_940: string = '94%'
export const THOUSANDTH_1000: string = '100%'
export const DEFAULT_2: number = 2
export const DEFAULT_8: number = 8
export const DEFAULT_12: number = 12
export const DEFAULT_10: number = 10
export const DEFAULT_16: number = 16
export const DEFAULT_18: number = 18
export const DEFAULT_20: number = 20
export const DEFAULT_24: number = 24
export const DEFAULT_28: number = 28
export const DEFAULT_32: number = 32
export const DEFAULT_48: number = 48
export const DEFAULT_56: number = 56
export const DEFAULT_60: number = 60
export const LIST_ITEM_SPACE: number = 2
export const ADD_TASK_TITLE: string = '添加任务'
export const EDIT_TASK_TITLE: string = '编辑任务'
export const SETTING_FINISHED_MESSAGE = '设置完成!!!'
export const CHOOSE_TIME_OUT_RANGE: string = '选择时间超出范围'
export const TODAY: string = new Date().toDateString()
export const DEFAULT_TIME: string = '08:00'
export const GET_UP_TIME_RANGE: string = '(06:00 - 09:00)'
export const SLEEP_TIME_RANGE: string = '(20:00 - 23:00)'
export const GET_UP_EARLY_TIME: string = '06:00'
export const GET_UP_LATE_TIME: string = '09:00'
export const SLEEP_EARLY_TIME: string = '20:00'
export const SLEEP_LATE_TIME: string = '23:00'
export const DEFAULT_SELECTED_TIME: Date = new Date(`${TODAY} 8:00:00`)
export const EVERYDAY: string = '每天'
export const NO_LENGTH: number = 0
export const INIT_WEEK_IDS: string = '1, 2, 3, 4, 5, 6, 7'
export const PER_DAY: string = '/ 天'
export const ZERO: number = 0
export const MINUS_20: number = -20
export const HAS_NO_INDEX: number = -1
export const DRINK_STEP: number = 25
export const DRINK_MAX_RANGE: number = 500
export const TIMES_100: number = 100
export const EAT_APPLE_RANGE: number = 100
export const DEFAULT_TEXT: string = '0.25'
export const DEFAULT_APPLE: string = '1'
添加任务
首页组件
// ets/pages/Index.ets
import TaskList from '../view/TaskList'
import { TaskListItem, TaskInitList } from '../model/TaskInitList'
import { THOUSANDTH_1000, ADD_TASK_TITLE } from '../common/constants/CommonConstant'
@Entry
@Component
struct Index {
@Provide taskList: TaskListItem[] = TaskInitList
build() {
Row() {
Navigation() {
Column() {
TaskList()
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.Center)
}
.size({ width: THOUSANDTH_1000, height: THOUSANDTH_1000 })
.title(ADD_TASK_TITLE)
.titleMode(NavigationTitleMode.Mini)
}
.backgroundColor($r('app.color.primaryBgColor'))
.height(THOUSANDTH_1000)
}
}
任务列表初始化
// ets/model/TaskInitList.ets
export interface TaskListItem {
taskID: number
taskName: Resource
isOpen: boolean
unit: string
icon: Resource
targetValue: string
isAlarm: boolean
startTime: string
frequency: string
}
export interface FrequencyContentType {
id: number,
label: string,
isChecked: boolean
}
export const TaskInitList: TaskListItem[] = [
{ // Get up early.
taskID: 1,
taskName: $r('app.string.task_morning'),
icon: $r('app.media.morning'),
targetValue: '08: 00',
isOpen: true,
unit: '',
isAlarm: false,
startTime: '08: 00',
frequency: '1, 2, 3, 4, 5, 6, 7'
},
{ // Drink water.
taskID: 2,
taskName: $r('app.string.task_water'),
icon: $r('app.media.water'),
targetValue: '0.25',
isOpen: true,
unit: 'L',
isAlarm: false,
startTime: '08: 00',
frequency: '1, 2, 3, 4, 5, 6, 7'
},
{ // Eat apples.
taskID: 3,
taskName: $r('app.string.task_apple'),
icon: $r('app.media.apple'),
targetValue: '1',
isOpen: true,
unit: '个',
isAlarm: false,
startTime: '08: 00',
frequency: '1, 2, 3, 4, 5, 6, 7'
},
{ // Smile every day.
taskID: 4,
taskName: $r('app.string.task_smile'),
icon: $r('app.media.smile'),
targetValue: '1',
isOpen: false,
unit: '次',
isAlarm: false,
startTime: '08: 00',
frequency: '1, 2, 3, 4, 5, 6, 7'
},
{ // Clean one’s teeth.
taskID: 5,
taskName: $r('app.string.task_brush'),
icon: $r('app.media.brush'),
targetValue: '1',
isOpen: false,
unit: '次',
isAlarm: false,
startTime: '08: 00',
frequency: '1, 2, 3, 4, 5, 6, 7'
},
{ // Go to bed early.
taskID: 6,
taskName: $r('app.string.task_night'),
icon: $r('app.media.night'),
targetValue: '20: 00',
isOpen: false,
unit: '',
isAlarm: false,
startTime: '08: 00',
frequency: '1, 2, 3, 4, 5, 6, 7'
}
]
任务列表视图
// ets/view/TaskList.ets
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
@Component
export default struct TaskList {
@Consume taskList: TaskListItem[]
build() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ForEach(this.taskList, (item: TaskListItem) => {
ListItem() {
Row() {
Row() {
Image(item?.icon)
.width(commonConst.DEFAULT_24)
.height(commonConst.DEFAULT_24)
.margin({ right: commonConst.DEFAULT_8 })
Text(item?.taskName)
.fontSize(commonConst.DEFAULT_20)
.fontColor($r('app.color.titleColor'))
}
.width(commonConst.THOUSANDTH_500)
Blank()
.layoutWeight(1)
if (item?.isOpen) {
Text($r('app.string.already_open'))
.fontSize(commonConst.DEFAULT_16)
.flexGrow(1)
.align(Alignment.End)
.margin({ right: commonConst.DEFAULT_8 })
.fontColor($r('app.color.titleColor'))
}
Image($r('app.media.right_grey'))
.width(commonConst.DEFAULT_8)
.height(commonConst.DEFAULT_16)
}
.width(commonConst.THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
.height(commonConst.THOUSANDTH_80)
.borderRadius(commonConst.DEFAULT_12)
.backgroundColor($r('app.color.white'))
})
}
.height(commonConst.THOUSANDTH_1000)
.width(commonConst.THOUSANDTH_940)
}
}
任务编辑页
添加跳转
// ets/view/TaskList.ets
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import { router } from '@kit.ArkUI'
import { formatParams } from '../viewModel/TaskTargetSetting'
@Component
export default struct TaskList {
@Consume taskList: TaskListItem[]
build() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ForEach(this.taskList, (item: TaskListItem) => {
ListItem() {
Row() {
Row() {
Image(item?.icon)
.width(commonConst.DEFAULT_24)
.height(commonConst.DEFAULT_24)
.margin({ right: commonConst.DEFAULT_8 })
Text(item?.taskName)
.fontSize(commonConst.DEFAULT_20)
.fontColor($r('app.color.titleColor'))
}
.width(commonConst.THOUSANDTH_500)
Blank()
.layoutWeight(1)
if (item?.isOpen) {
Text($r('app.string.already_open'))
.fontSize(commonConst.DEFAULT_16)
.flexGrow(1)
.align(Alignment.End)
.margin({ right: commonConst.DEFAULT_8 })
.fontColor($r('app.color.titleColor'))
}
Image($r('app.media.right_grey'))
.width(commonConst.DEFAULT_8)
.height(commonConst.DEFAULT_16)
}
.width(commonConst.THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
.height(commonConst.THOUSANDTH_80)
.borderRadius(commonConst.DEFAULT_12)
.backgroundColor($r('app.color.white'))
// 1. 添加链接
.onClick(() => {
router.pushUrl({
url: 'pages/TaskEditPage',
params: {
params: formatParams(item)
}
})
})
})
}
.height(commonConst.THOUSANDTH_1000)
.width(commonConst.THOUSANDTH_940)
}
}
任务目标设置模型(formatParams)
// ets/viewModel/TaskTargetSetting
import { TaskListItem } from '../model/TaskInitList'
export const formatParams = (params: TaskListItem) => {
return JSON.stringify(params)
}
编辑页面
// ets/pages/TaskEditPage.ets
import { THOUSANDTH_1000, EDIT_TASK_TITLE } from '../common/constants/CommonConstant'
import TaskDetail from '../view/TaskDetail'
@Entry
@Component
struct TaskEdit {
build() {
Row() {
Navigation() {
Column() {
TaskDetail()
}
.width(THOUSANDTH_1000)
.height(THOUSANDTH_1000)
}
.size({ width: THOUSANDTH_1000, height: THOUSANDTH_1000 })
.title(EDIT_TASK_TITLE)
.titleMode(NavigationTitleMode.Mini)
}
.height(THOUSANDTH_1000)
.backgroundColor($r('app.color.primaryBgColor'))
}
}
详情页
// ets/view/TaskDetail.ets
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {
TaskChooseItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
@Styles
function listItemStyle() {
.backgroundColor($r('app.color.white'))
.height(commonConst.DEFAULT_56)
.borderRadius(commonConst.DEFAULT_10)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
@Component
export default struct TaskDetail {
@Provide settingParams: TaskListItem = this.parseRouterParams()
parseRouterParams() {
let params = router.getParams() as Record<string, Object>
const routerParams: TaskListItem = JSON.parse(params.params as string)
return routerParams
}
build() {
Column() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ListItem() {
TaskChooseItem()
}
.listItemStyle()
}
}
.width(commonConst.THOUSANDTH_1000)
}
}
任务编辑列表项
// ets/view/TaskEditListItem.ets
import { TaskListItem } from '../model/TaskInitList'
import {
DEFAULT_20,
DEFAULT_32,
DEFAULT_56,
THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
@Component
export struct TaskChooseItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen })
.width(DEFAULT_56)
.height(DEFAULT_32)
.selectedColor($r('app.color.blueColor'))
.onChange((isOn: boolean) => {
this.settingParams.isOpen = isOn;
})
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
目标设置展示
引入目标设置
// ets/view/TaskDetail.ets
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {
TaskChooseItem,
// 2. 引入TargetSetItem
TargetSetItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'
@Styles
function listItemStyle() {
.backgroundColor($r('app.color.white'))
.height(commonConst.DEFAULT_56)
.borderRadius(commonConst.DEFAULT_10)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
@Component
export default struct TaskDetail {
@Provide settingParams: TaskListItem = this.parseRouterParams()
parseRouterParams() {
let params = router.getParams() as Record<string, Object>
const routerParams: TaskListItem = JSON.parse(params.params as string)
return routerParams
}
build() {
Column() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ListItem() {
TaskChooseItem()
}
.listItemStyle()
// 1. 目标设置入口
ListItem() {
TargetSetItem()
}
.listItemStyle()
.enabled(
this.settingParams?.isOpen &&
(this.settingParams?.taskID !== taskType.smile) &&
(this.settingParams?.taskID !== taskType.brushTeeth)
)
}
.width(commonConst.THOUSANDTH_940)
}
.width(commonConst.THOUSANDTH_1000)
}
}
目标设置展示实现
// ets/view/TaskEditListItem.ets
import { TaskListItem } from '../model/TaskInitList'
import {
DEFAULT_16,
DEFAULT_20,
DEFAULT_32,
DEFAULT_56,
DEFAULT_8,
PER_DAY,
THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
// 2.定义公共样式targetSetCommon
@Extend(Text)
function targetSetCommon() {
.fontSize(DEFAULT_16)
.flexGrow(1)
.margin({ right: DEFAULT_8 })
.align(Alignment.End)
}
// 2.定义公共样式targetSettingStyle
@Extend(Text)
function targetSettingStyle(isOpen: boolean, taskID: number) {
.fontColor(isOpen && taskID !== taskType.smile && taskID !== taskType.brushTeeth ?
$r('app.color.titleColor') :
$r('app.color.disabledColor'))
}
@Component
export struct TaskChooseItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen })
.width(DEFAULT_56)
.height(DEFAULT_32)
.selectedColor($r('app.color.blueColor'))
.onChange((isOn: boolean) => {
this.settingParams.isOpen = isOn;
})
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
// 1. 定义TargetSetItem组件
@Component
export struct TargetSetItem {
@Consume settingParams: TaskListItem;
build() {
Row() {
Text($r('app.string.target_setting'))
.fontSize(DEFAULT_20)
.fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
if (this.settingParams?.unit === '') {
Text(`${this.settingParams?.targetValue}`)
.targetSetCommon()
.targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)
} else {
Text(`${this.settingParams?.targetValue} ${this.settingParams?.unit} ${PER_DAY}`)
.targetSetCommon()
.targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)
}
Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16);
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
TaskInfo 枚举模型设置
// ets/model/TaskInfo.ets
export enum taskType {
'getup' = 1,
'drinkWater',
'eatApple',
'smile',
'brushTeeth',
'sleepEarly'
}
弹窗构造逻辑
定义单击事件
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {
TaskChooseItem,
TargetSetItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'
// 4. 引入BroadCast(先去创建)
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { CustomDialogView } from './CustomDialogView'
@Styles
function listItemStyle() {
.backgroundColor($r('app.color.white'))
.height(commonConst.DEFAULT_56)
.borderRadius(commonConst.DEFAULT_10)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
@Component
export default struct TaskDetail {
@Provide settingParams: TaskListItem = this.parseRouterParams()
// 5. 提供 broadCast
@Provide broadCast: BroadCast = new BroadCast()
parseRouterParams() {
let params = router.getParams() as Record<string, Object>
const routerParams: TaskListItem = JSON.parse(params.params as string)
return routerParams
}
// 7. 先去定义弹窗和builder,注册(on)完,这里解绑
aboutToAppear() {
this.broadCast.off()
}
build() {
Column() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ListItem() {
TaskChooseItem()
}
.listItemStyle()
ListItem() {
TargetSetItem()
}
.listItemStyle()
// 3. 设置 smile & brushTeeth 不可单击
.enabled(
this.settingParams?.isOpen &&
(this.settingParams?.taskID !== taskType.smile) &&
(this.settingParams?.taskID !== taskType.brushTeeth)
)
// 1. 定义单击事件
.onClick(() => {
// 2. 测试单击,目的是引出第 3 步
// console.log('test')
// 8. 最后再触发
this.broadCast.emit(
BroadCastType.SHOW_TARGET_SETTING_DIALOG)
})
// 9. 测试提醒时间设置
ListItem() {
Text('提醒时间')
}
.listItemStyle()
.enabled(this.settingParams?.isOpen && this.settingParams?.isAlarm)
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_REMIND_TIME_DIALOG
)
})
// 9. 测试频率设置
ListItem() {
Text('频率')
}
.listItemStyle()
.enabled(this.settingParams?.isOpen)
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_FREQUENCY_DIALOG
)
})
}
// 6.定义弹框视图(先去创建)
CustomDialogView()
}
.width(commonConst.THOUSANDTH_1000)
}
}
定义 BroadCast
// ets/common/util/BroadCast.ets
export class BroadCast {
private callBackArray = []
public on(event: string, callback: Function) {
(this.callBackArray[event] || (this.callBackArray[event] = [])).push(callback)
}
public off() {
this.callBackArray = []
}
public emit(event: string) {
let _self = this
if (!this.callBackArray[event]) {
return
}
let cbs: Function[] = this.callBackArray[event]
if (cbs) {
let len = cbs.length;
for (let i = 0; i < len; i++) {
try {
cbs[i](_self)
} catch (e) {
new Error(e)
}
}
}
}
}
export enum BroadCastType {
SHOW_TARGET_SETTING_DIALOG = 'showTargetSettingDialog',
SHOW_REMIND_TIME_DIALOG = 'showRemindTimeDialog',
SHOW_FREQUENCY_DIALOG = 'showFrequencyDialog'
}
定义弹窗视图
// ets/view/CustomDialogView.ets
import { TargetSettingDialog, RemindTimeDialog, FrequencyDialog } from './TaskSettingDialog'
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { ZERO, MINUS_20 } from '../common/constants/CommonConstant'
@Component
export struct CustomDialogView {
@State isShow: boolean = false
@Provide achievementLevel: number = 3
@Consume broadCast: BroadCast
targetSettingDialogController: CustomDialogController = new CustomDialogController({
builder: TargetSettingDialog(),
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: ZERO, dy: MINUS_20 }
})
RemindTimeDialogController: CustomDialogController = new CustomDialogController({
builder: RemindTimeDialog(),
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: ZERO, dy: MINUS_20 }
});
FrequencyDialogController: CustomDialogController = new CustomDialogController({
builder: FrequencyDialog(),
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: ZERO, dy: MINUS_20 }
})
aboutToAppear() {
let self = this
this.broadCast.on(
BroadCastType.SHOW_TARGET_SETTING_DIALOG,
() => {
self.targetSettingDialogController.open()
})
this.broadCast.on(
BroadCastType.SHOW_REMIND_TIME_DIALOG,
() => {
self.RemindTimeDialogController.open()
})
this.broadCast.on(
BroadCastType.SHOW_FREQUENCY_DIALOG,
() => {
self.FrequencyDialogController.open()
})
}
build() {
}
}
定义弹窗 builder 组件
// ets/view/TaskSettingDialog.ets
import * as commonConst from '../common/constants/CommonConstant'
@CustomDialog
export struct TargetSettingDialog {
controller: CustomDialogController = new CustomDialogController({
builder: TargetSettingDialog()
})
build() {
Column() {
Text('target setting dialog')
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
@CustomDialog
export struct RemindTimeDialog {
controller: CustomDialogController = new CustomDialogController({
builder: RemindTimeDialog()
})
build() {
Column() {
Text('remind time dialog')
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
@CustomDialog
export struct FrequencyDialog {
controller: CustomDialogController = new CustomDialogController({
builder: FrequencyDialog()
})
build() {
Column() {
Text('frequency dialog')
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
目标设置弹窗实现
目标设置窗口逻辑
// ets/view/TaskSettingDialog.ets
import * as commonConst from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
import { TaskListItem } from '../model/TaskInitList'
import { createAppleRange, createDrinkRange, formatTime, returnTimeStamp } from '../viewModel/TaskTargetSetting'
import { promptAction } from '@kit.ArkUI'
@CustomDialog
export struct TargetSettingDialog {
controller: CustomDialogController = new CustomDialogController({
builder: TargetSettingDialog()
})
@Consume settingParams: TaskListItem
currentTime: string = commonConst.DEFAULT_TIME
currentValue: string = this.settingParams.taskID === taskType.drinkWater ? commonConst.DEFAULT_TEXT :
commonConst.DEFAULT_APPLE
drinkRange: string[] = createDrinkRange()
appleRange: string[] = createAppleRange()
createSubTitle() {
if (this.settingParams.taskID === taskType.getup) {
return commonConst.GET_UP_TIME_RANGE
}
if (this.settingParams.taskID === taskType.sleepEarly) {
return commonConst.SLEEP_TIME_RANGE
}
return ''
}
setTargetValue() {
if (this.settingParams.taskID === taskType.getup) {
if (!this.compareTime(commonConst.GET_UP_EARLY_TIME, commonConst.GET_UP_LATE_TIME)) {
return
}
this.settingParams.targetValue = this.currentTime
return
}
if (this.settingParams.taskID === taskType.sleepEarly) {
if (!this.compareTime(commonConst.SLEEP_EARLY_TIME, commonConst.SLEEP_LATE_TIME)) {
return
}
this.settingParams.targetValue = this.currentTime
return
}
this.settingParams.targetValue = this.currentValue
}
compareTime(startTime: string, endTime: string) {
if (returnTimeStamp(this.currentTime) < returnTimeStamp(startTime) ||
returnTimeStamp(this.currentTime) > returnTimeStamp(endTime)) {
promptAction.showToast({
message: commonConst.CHOOSE_TIME_OUT_RANGE
})
return false
}
return true
}
build() {
Column() {
Row() {
Text($r('app.string.target_setting')).fontSize(commonConst.DEFAULT_20).margin({ right: commonConst.DEFAULT_12 })
Text(this.createSubTitle())
.fontSize(commonConst.DEFAULT_16)
}
.width(commonConst.THOUSANDTH_1000)
.justifyContent(FlexAlign.Start)
if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams.taskID) > commonConst.HAS_NO_INDEX) {
TimePicker({
selected: commonConst.DEFAULT_SELECTED_TIME
})
.height(commonConst.THOUSANDTH_800)
.useMilitaryTime(true)
.onChange((value: TimePickerResult) => {
this.currentTime = formatTime(value)
})
} else {
TextPicker({ range: this.settingParams.taskID === taskType.drinkWater ? this.drinkRange : this.appleRange,
value: this.settingParams.targetValue })
.width(commonConst.THOUSANDTH_900)
.height(commonConst.THOUSANDTH_800)
.onChange((value: string | string[]) => {
this.currentValue = (value as string)?.split(' ')[0]
})
}
Row() {
Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.currentTime = commonConst.DEFAULT_TIME
this.currentValue = commonConst.DEFAULT_TEXT
this.controller.close()
})
Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.setTargetValue()
this.controller.close()
})
}
.justifyContent(FlexAlign.SpaceAround)
.width(commonConst.THOUSANDTH_1000)
.height(commonConst.DEFAULT_28)
.margin({ bottom: commonConst.DEFAULT_20 })
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
@CustomDialog
export struct RemindTimeDialog {
controller: CustomDialogController = new CustomDialogController({
builder: RemindTimeDialog()
})
build() {
Column() {
Text('remind time dialog')
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
@CustomDialog
export struct FrequencyDialog {
controller: CustomDialogController = new CustomDialogController({
builder: FrequencyDialog()
})
build() {
Column() {
Text('frequency dialog')
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
任务目标设置视图模型
// ets/TaskTargetSetting.ets
import { DRINK_MAX_RANGE, DRINK_STEP, EAT_APPLE_RANGE, TIMES_100, TODAY } from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import { padTo2Digits } from './FrequencySetting'
export const formatParams = (params: TaskListItem) => {
return JSON.stringify(params)
}
export const formatTime = (value: TimePickerResult) => {
let hour: number = 0
let minute: number = 0
if (value.hour !== undefined && value.minute !== undefined) {
hour = value.hour
minute = value.minute
}
return `${padTo2Digits(hour)}:${padTo2Digits(minute)}`
}
export const createDrinkRange = () => {
const drinkRangeArr: string[] = []
for (let i = DRINK_STEP; i <= DRINK_MAX_RANGE; i += DRINK_STEP) {
drinkRangeArr.push(`${i / TIMES_100} L`)
}
return drinkRangeArr
}
export const createAppleRange = () => {
const appleRangeArr: string[] = []
for (let i = 1; i <= EAT_APPLE_RANGE; i++) {
appleRangeArr.push(`${i} 个`)
}
return appleRangeArr
}
export const returnTimeStamp = (currentTime: string) => {
const timeString = `${TODAY} ${currentTime}`
return new Date(timeString).getTime()
}
频率设置视图模型
// ets/viewModel/FrequencySetting.ets
export function padTo2Digits(num: number) {
return num.toString().padStart(2, '0')
}
时间提醒弹窗实现
更新TaskDetail
// ets/view/TaskDetail.ets
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {
TaskChooseItem,
TargetSetItem,
// 3. 导入模块
OpenRemindItem,
RemindTimeItem
} from './TaskEditListItem'
import { router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { CustomDialogView } from './CustomDialogView'
@Styles
function listItemStyle() {
.backgroundColor($r('app.color.white'))
.height(commonConst.DEFAULT_56)
.borderRadius(commonConst.DEFAULT_10)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
@Component
export default struct TaskDetail {
@Provide settingParams: TaskListItem = this.parseRouterParams()
@Provide broadCast: BroadCast = new BroadCast()
parseRouterParams() {
let params = router.getParams() as Record<string, Object>
const routerParams: TaskListItem = JSON.parse(params.params as string)
return routerParams
}
aboutToAppear() {
this.broadCast.off()
}
build() {
Column() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ListItem() {
TaskChooseItem()
}
.listItemStyle()
ListItem() {
TargetSetItem()
}
.listItemStyle()
.enabled(
this.settingParams?.isOpen &&
(this.settingParams?.taskID !== taskType.smile) &&
(this.settingParams?.taskID !== taskType.brushTeeth)
)
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_TARGET_SETTING_DIALOG)
})
// 1.构造编辑列表相应内容
ListItem() {
OpenRemindItem()
}
.listItemStyle()
.enabled(this.settingParams.isOpen)
ListItem() {
// 2.构造编辑列表相应内容
RemindTimeItem()
}
.listItemStyle()
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_REMIND_TIME_DIALOG
)
})
ListItem() {
Text('频率')
}
.listItemStyle()
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_FREQUENCY_DIALOG
)
})
}
CustomDialogView()
}
.width(commonConst.THOUSANDTH_1000)
}
}
实现编辑任务列表的开启提醒与提醒时间
import { TaskListItem } from '../model/TaskInitList'
import {
DEFAULT_16,
DEFAULT_20,
DEFAULT_32,
DEFAULT_56,
DEFAULT_8,
PER_DAY,
THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
@Extend(Text)
function targetSetCommon() {
.fontSize(DEFAULT_16)
.flexGrow(1)
.margin({ right: DEFAULT_8 })
.align(Alignment.End)
}
@Extend(Text)
function targetSettingStyle(isOpen: boolean, taskID: number) {
.fontColor(isOpen && taskID !== taskType.smile && taskID !== taskType.brushTeeth ?
$r('app.color.titleColor') :
$r('app.color.disabledColor'))
}
@Extend(Text)
function remindTimeStyle(isOpen: boolean, isAlarm: boolean) {
.fontColor(isOpen && isAlarm ? $r('app.color.titleColor') : $r('app.color.disabledColor'))
}
@Component
export struct TaskChooseItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen })
.width(DEFAULT_56)
.height(DEFAULT_32)
.selectedColor($r('app.color.blueColor'))
.onChange((isOn: boolean) => {
this.settingParams.isOpen = isOn;
})
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
@Component
export struct TargetSetItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text($r('app.string.target_setting'))
.fontSize(DEFAULT_20)
.fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
if (this.settingParams?.unit === '') {
Text(`${this.settingParams?.targetValue}`)
.targetSetCommon()
.targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)
} else {
Text(`${this.settingParams?.targetValue} ${this.settingParams?.unit} ${PER_DAY}`)
.targetSetCommon()
.targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)
}
Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16);
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
// 1.实现开启提醒
@Component
export struct OpenRemindItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text($r('app.string.open_reminder'))
.fontSize(DEFAULT_20)
.fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.settingParams?.isAlarm })
.width(DEFAULT_56)
.height(DEFAULT_32)
.selectedColor($r('app.color.blueColor'))
.onChange((isOn: boolean) => {
this.settingParams.isAlarm = isOn
})
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
// 2.实现提醒时间
@Component
export struct RemindTimeItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text($r('app.string.remind_time')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
Text(this.settingParams?.startTime)
.targetSetCommon()
.remindTimeStyle(this.settingParams.isOpen, this.settingParams.isAlarm)
Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16)
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
实现时间提醒弹窗
import * as commonConst from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
import { TaskListItem } from '../model/TaskInitList'
import { createAppleRange, createDrinkRange, formatTime, returnTimeStamp } from '../viewModel/TaskTargetSetting'
import { promptAction } from '@kit.ArkUI'
@CustomDialog
export struct TargetSettingDialog {
controller: CustomDialogController = new CustomDialogController({
builder: TargetSettingDialog()
})
@Consume settingParams: TaskListItem
currentTime: string = commonConst.DEFAULT_TIME
currentValue: string = this.settingParams.taskID === taskType.drinkWater ? commonConst.DEFAULT_TEXT :
commonConst.DEFAULT_APPLE
drinkRange: string[] = createDrinkRange()
appleRange: string[] = createAppleRange()
createSubTitle() {
if (this.settingParams.taskID === taskType.getup) {
return commonConst.GET_UP_TIME_RANGE
}
if (this.settingParams.taskID === taskType.sleepEarly) {
return commonConst.SLEEP_TIME_RANGE
}
return ''
}
setTargetValue() {
if (this.settingParams.taskID === taskType.getup) {
if (!this.compareTime(commonConst.GET_UP_EARLY_TIME, commonConst.GET_UP_LATE_TIME)) {
return
}
this.settingParams.targetValue = this.currentTime
return
}
if (this.settingParams?.taskID === taskType.sleepEarly) {
if (!this.compareTime(commonConst.SLEEP_EARLY_TIME, commonConst.SLEEP_LATE_TIME)) {
return
}
this.settingParams.targetValue = this.currentTime
return
}
this.settingParams.targetValue = this.currentValue
}
compareTime(startTime: string, endTime: string) {
if (returnTimeStamp(this.currentTime) < returnTimeStamp(startTime) ||
returnTimeStamp(this.currentTime) > returnTimeStamp(endTime)) {
promptAction.showToast({
message: commonConst.CHOOSE_TIME_OUT_RANGE
})
return false
}
return true
}
build() {
Column() {
Row() {
Text($r('app.string.target_setting')).fontSize(commonConst.DEFAULT_20).margin({ right: commonConst.DEFAULT_12 })
Text(this.createSubTitle())
.fontSize(commonConst.DEFAULT_16)
}
.width(commonConst.THOUSANDTH_1000)
.justifyContent(FlexAlign.Start)
if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams.taskID) > commonConst.HAS_NO_INDEX) {
TimePicker({
selected: commonConst.DEFAULT_SELECTED_TIME
})
.height(commonConst.THOUSANDTH_800)
.useMilitaryTime(true)
.onChange((value: TimePickerResult) => {
this.currentTime = formatTime(value)
})
} else {
TextPicker({ range: this.settingParams?.taskID === taskType.drinkWater ? this.drinkRange : this.appleRange,
value: this.settingParams.targetValue })
.width(commonConst.THOUSANDTH_900)
.height(commonConst.THOUSANDTH_800)
.onChange((value: string | string[]) => {
this.currentValue = (value as string)?.split(' ')[0]
})
}
Row() {
Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.currentTime = commonConst.DEFAULT_TIME;
this.currentValue = commonConst.DEFAULT_TEXT;
this.controller.close()
})
Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.setTargetValue()
this.controller.close()
})
}
.justifyContent(FlexAlign.SpaceAround)
.width(commonConst.THOUSANDTH_1000)
.height(commonConst.DEFAULT_28)
.margin({ bottom: commonConst.DEFAULT_20 })
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
// 实现时间提醒弹窗
@CustomDialog
export struct RemindTimeDialog {
controller: CustomDialogController = new CustomDialogController({
builder: RemindTimeDialog()
})
currentTime: string = commonConst.DEFAULT_TIME
@Consume settingParams: TaskListItem
build() {
Column() {
Column() {
Text($r('app.string.remind_time'))
.fontSize(commonConst.DEFAULT_20)
.margin({ top: commonConst.DEFAULT_10 })
.width(commonConst.THOUSANDTH_1000)
.textAlign(TextAlign.Start)
}
.width(commonConst.THOUSANDTH_900)
TimePicker({
selected: commonConst.DEFAULT_SELECTED_TIME
})
.height(commonConst.THOUSANDTH_800)
.useMilitaryTime(true)
.onChange((value: TimePickerResult) => {
this.currentTime = formatTime(value)
})
Row() {
Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.currentTime = commonConst.DEFAULT_TIME
this.controller.close()
})
Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.settingParams.startTime = this.currentTime
this.controller.close()
})
}
.justifyContent(FlexAlign.SpaceAround)
.width(commonConst.THOUSANDTH_1000)
.height(commonConst.DEFAULT_28)
.margin({ bottom: commonConst.DEFAULT_20 })
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
@CustomDialog
export struct FrequencyDialog {
controller: CustomDialogController = new CustomDialogController({
builder: FrequencyDialog()
})
build() {
Column() {
Text('frequency dialog')
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
频率弹窗和提交完成的实现
// ets/view/TaskDetail.ets
import * as commonConst from '../common/constants/CommonConstant'
import { TaskListItem } from '../model/TaskInitList'
import {
TaskChooseItem,
TargetSetItem,
OpenRemindItem,
RemindTimeItem,
FrequencyItem
} from './TaskEditListItem'
import { promptAction, router } from '@kit.ArkUI'
import { taskType } from '../model/TaskInfo'
import { BroadCast, BroadCastType } from '../common/utils/BroadCast'
import { CustomDialogView } from './CustomDialogView'
@Styles
function listItemStyle() {
.backgroundColor($r('app.color.white'))
.height(commonConst.DEFAULT_56)
.borderRadius(commonConst.DEFAULT_10)
.padding({ left: commonConst.DEFAULT_12, right: commonConst.DEFAULT_12 })
}
@Component
export default struct TaskDetail {
@Provide settingParams: TaskListItem = this.parseRouterParams()
@Provide broadCast: BroadCast = new BroadCast()
@Provide frequency: string = commonConst.EVERYDAY
parseRouterParams() {
let params = router.getParams() as Record<string, Object>
const routerParams: TaskListItem = JSON.parse(params.params as string)
return routerParams
}
aboutToAppear() {
this.broadCast.off()
}
finishTaskEdit() {
promptAction.showToast({
message: commonConst.SETTING_FINISHED_MESSAGE
})
}
build() {
Column() {
List({ space: commonConst.LIST_ITEM_SPACE }) {
ListItem() {
TaskChooseItem()
}
.listItemStyle()
ListItem() {
TargetSetItem()
}
.listItemStyle()
.enabled(
this.settingParams?.isOpen &&
(this.settingParams?.taskID !== taskType.smile) &&
(this.settingParams?.taskID !== taskType.brushTeeth)
)
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_TARGET_SETTING_DIALOG)
})
ListItem() {
OpenRemindItem()
}
.listItemStyle()
.enabled(this.settingParams?.isOpen)
ListItem() {
RemindTimeItem()
}
.listItemStyle()
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_REMIND_TIME_DIALOG
)
})
// 1. 引入FrequencyItem
ListItem() {
FrequencyItem()
}
.listItemStyle()
.onClick(() => {
this.broadCast.emit(
BroadCastType.SHOW_FREQUENCY_DIALOG
)
})
}
.width(commonConst.THOUSANDTH_940)
// x. 最后实现完成按钮提交
Button() {
Text($r('app.string.complete')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
}
.width(commonConst.THOUSANDTH_800)
.height(commonConst.DEFAULT_48)
.backgroundColor($r('app.color.borderColor'))
.onClick(() => {
this.finishTaskEdit()
})
.position({
x: commonConst.THOUSANDTH_100,
y: commonConst.THOUSANDTH_800
})
CustomDialogView()
}
.width(commonConst.THOUSANDTH_1000)
}
}
实现频率任务项视图
// ets/view/TaskEditListItem.ets
import { TaskListItem } from '../model/TaskInitList'
import {
DEFAULT_12,
DEFAULT_16,
DEFAULT_20,
DEFAULT_32,
DEFAULT_56,
DEFAULT_8,
PER_DAY,
THOUSANDTH_1000,
} from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
@Extend(Text)
function targetSetCommon() {
.fontSize(DEFAULT_16)
.flexGrow(1)
.margin({ right: DEFAULT_8 })
.align(Alignment.End)
}
@Extend(Text)
function targetSettingStyle(isOpen: boolean, taskID: number) {
.fontColor(isOpen && taskID !== taskType.smile && taskID !== taskType.brushTeeth ?
$r('app.color.titleColor') :
$r('app.color.disabledColor'))
}
@Extend(Text)
function remindTimeStyle(isOpen: boolean, isAlarm: boolean) {
.fontColor(isOpen && isAlarm ? $r('app.color.titleColor') : $r('app.color.disabledColor'))
}
@Extend(Text)
function frequencyStyle(isOpen: boolean) {
.fontSize(DEFAULT_12)
.flexGrow(1)
.margin({ right: DEFAULT_8 })
.textAlign(TextAlign.End)
.fontColor(isOpen ? $r('app.color.titleColor') : $r('app.color.disabledColor'))
}
@Component
export struct TaskChooseItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text(this.settingParams.taskName).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Toggle({ type: ToggleType.Switch, isOn: this.settingParams.isOpen })
.width(DEFAULT_56)
.height(DEFAULT_32)
.selectedColor($r('app.color.blueColor'))
.onChange((isOn: boolean) => {
this.settingParams.isOpen = isOn;
})
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
@Component
export struct TargetSetItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text($r('app.string.target_setting'))
.fontSize(DEFAULT_20)
.fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
if (this.settingParams?.unit === '') {
Text(`${this.settingParams?.targetValue}`)
.targetSetCommon()
.targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)
} else {
Text(`${this.settingParams?.targetValue} ${this.settingParams?.unit} ${PER_DAY}`)
.targetSetCommon()
.targetSettingStyle(this.settingParams?.isOpen, this.settingParams?.taskID)
}
Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16);
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
@Component
export struct OpenRemindItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text($r('app.string.open_reminder'))
.fontSize(DEFAULT_20)
.fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.settingParams?.isAlarm })
.width(DEFAULT_56)
.height(DEFAULT_32)
.selectedColor($r('app.color.blueColor'))
.onChange((isOn: boolean) => {
this.settingParams.isAlarm = isOn
})
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
@Component
export struct RemindTimeItem {
@Consume settingParams: TaskListItem
build() {
Row() {
Text($r('app.string.remind_time')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Blank()
.layoutWeight(1)
Text(this.settingParams?.startTime)
.targetSetCommon()
.remindTimeStyle(this.settingParams.isOpen, this.settingParams.isAlarm)
Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16)
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
// 1. 实现频率任务项视图
@Component
export struct FrequencyItem {
@Consume settingParams: TaskListItem
@Consume frequency: string
build() {
Row() {
Text($r('app.string.frequency')).fontSize(DEFAULT_20).fontWeight(FontWeight.Medium)
Text(this.frequency)
.targetSetCommon()
.frequencyStyle(this.settingParams.isOpen)
Image($r('app.media.right_grey')).width(DEFAULT_8).height(DEFAULT_16)
}
.width(THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
}
}
实现频率设置弹窗
// ets/view/TaskSettingDialog.ets
import * as commonConst from '../common/constants/CommonConstant'
import { taskType } from '../model/TaskInfo'
import { FrequencyContentType, TaskListItem } from '../model/TaskInitList'
import { createAppleRange, createDrinkRange, formatTime, returnTimeStamp } from '../viewModel/TaskTargetSetting'
import { promptAction } from '@kit.ArkUI'
import { frequencyRange } from '../viewModel/FrequencySetting'
@CustomDialog
export struct TargetSettingDialog {
controller: CustomDialogController = new CustomDialogController({
builder: TargetSettingDialog()
})
@Consume settingParams: TaskListItem
currentTime: string = commonConst.DEFAULT_TIME
currentValue: string = this.settingParams.taskID === taskType.drinkWater ? commonConst.DEFAULT_TEXT :
commonConst.DEFAULT_APPLE
drinkRange: string[] = createDrinkRange()
appleRange: string[] = createAppleRange()
createSubTitle() {
if (this.settingParams.taskID === taskType.getup) {
return commonConst.GET_UP_TIME_RANGE
}
if (this.settingParams.taskID === taskType.sleepEarly) {
return commonConst.SLEEP_TIME_RANGE
}
return ''
}
setTargetValue() {
if (this.settingParams.taskID === taskType.getup) {
if (!this.compareTime(commonConst.GET_UP_EARLY_TIME, commonConst.GET_UP_LATE_TIME)) {
return
}
this.settingParams.targetValue = this.currentTime
return
}
if (this.settingParams?.taskID === taskType.sleepEarly) {
if (!this.compareTime(commonConst.SLEEP_EARLY_TIME, commonConst.SLEEP_LATE_TIME)) {
return
}
this.settingParams.targetValue = this.currentTime
return
}
this.settingParams.targetValue = this.currentValue
}
compareTime(startTime: string, endTime: string) {
if (returnTimeStamp(this.currentTime) < returnTimeStamp(startTime) ||
returnTimeStamp(this.currentTime) > returnTimeStamp(endTime)) {
promptAction.showToast({
message: commonConst.CHOOSE_TIME_OUT_RANGE
})
return false
}
return true
}
build() {
Column() {
Row() {
Text($r('app.string.target_setting')).fontSize(commonConst.DEFAULT_20).margin({ right: commonConst.DEFAULT_12 })
Text(this.createSubTitle())
.fontSize(commonConst.DEFAULT_16)
}
.width(commonConst.THOUSANDTH_1000)
.justifyContent(FlexAlign.Start)
if ([taskType.getup, taskType.sleepEarly].indexOf(this.settingParams.taskID) > commonConst.HAS_NO_INDEX) {
TimePicker({
selected: commonConst.DEFAULT_SELECTED_TIME
})
.height(commonConst.THOUSANDTH_800)
.useMilitaryTime(true)
.onChange((value: TimePickerResult) => {
this.currentTime = formatTime(value)
})
} else {
TextPicker({ range: this.settingParams?.taskID === taskType.drinkWater ? this.drinkRange : this.appleRange,
value: this.settingParams.targetValue })
.width(commonConst.THOUSANDTH_900)
.height(commonConst.THOUSANDTH_800)
.onChange((value: string | string[]) => {
this.currentValue = (value as string)?.split(' ')[0]
})
}
Row() {
Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.currentTime = commonConst.DEFAULT_TIME;
this.currentValue = commonConst.DEFAULT_TEXT;
this.controller.close()
})
Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.setTargetValue()
this.controller.close()
})
}
.justifyContent(FlexAlign.SpaceAround)
.width(commonConst.THOUSANDTH_1000)
.height(commonConst.DEFAULT_28)
.margin({ bottom: commonConst.DEFAULT_20 })
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
@CustomDialog
export struct RemindTimeDialog {
controller: CustomDialogController = new CustomDialogController({
builder: RemindTimeDialog()
})
currentTime: string = commonConst.DEFAULT_TIME
@Consume settingParams: TaskListItem
build() {
Column() {
Column() {
Text($r('app.string.remind_time'))
.fontSize(commonConst.DEFAULT_20)
.margin({ top: commonConst.DEFAULT_10 })
.width(commonConst.THOUSANDTH_1000)
.textAlign(TextAlign.Start)
}
.width(commonConst.THOUSANDTH_900)
TimePicker({
selected: commonConst.DEFAULT_SELECTED_TIME
})
.height(commonConst.THOUSANDTH_800)
.useMilitaryTime(true)
.onChange((value: TimePickerResult) => {
this.currentTime = formatTime(value);
})
Row() {
Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.currentTime = commonConst.DEFAULT_TIME
this.controller.close()
})
Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.settingParams.startTime = this.currentTime
this.controller.close()
})
}
.justifyContent(FlexAlign.SpaceAround)
.width(commonConst.THOUSANDTH_1000)
.height(commonConst.DEFAULT_28)
.margin({ bottom: commonConst.DEFAULT_20 })
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_560)
.padding(commonConst.DEFAULT_12)
}
}
// 1.实现频率设置弹窗
@CustomDialog
export struct FrequencyDialog {
controller: CustomDialogController = new CustomDialogController({
builder: FrequencyDialog()
})
private frequencyChooseRange: FrequencyContentType[] = frequencyRange()
private currentFrequency: string = commonConst.EVERYDAY
@Consume settingParams: TaskListItem
@Consume frequency: string
setFrequency() {
const checkedArr = this.frequencyChooseRange.filter((item: FrequencyContentType) => item.isChecked)
if (checkedArr.length === this.frequencyChooseRange.length || checkedArr.length === commonConst.NO_LENGTH) {
this.currentFrequency = commonConst.EVERYDAY
this.settingParams.frequency = commonConst.INIT_WEEK_IDS
return
}
this.currentFrequency = checkedArr.reduce((sum: string, current: FrequencyContentType) => {
return sum + ' ' + current.label
}, '')
this.settingParams.frequency = checkedArr.reduce((sum: string, current: FrequencyContentType) => {
return sum === '' ? sum + current.id : sum + ',' + current.id
}, '')
}
build() {
Column() {
Column() {
Text($r('app.string.set_your_frequency'))
.fontSize(commonConst.DEFAULT_20)
.margin({ top: commonConst.DEFAULT_10 })
.width(commonConst.THOUSANDTH_1000)
.textAlign(TextAlign.Start)
}
.width(commonConst.THOUSANDTH_900)
List() {
ForEach(this.frequencyChooseRange, (item: FrequencyContentType) => {
ListItem() {
Row() {
Text(item?.label).fontSize(commonConst.DEFAULT_20)
Toggle({ type: ToggleType.Checkbox })
.onChange((isOn: boolean) => {
item.isChecked = isOn
})
}
.width(commonConst.THOUSANDTH_1000)
.justifyContent(FlexAlign.SpaceBetween)
.height(commonConst.DEFAULT_60)
}
})
}
.divider({
strokeWidth: commonConst.DEFAULT_2,
color: $r('app.color.btnBgColor')
})
.flexGrow(1)
.padding(commonConst.DEFAULT_12)
.width(commonConst.THOUSANDTH_1000)
Row() {
Text($r('app.string.cancel')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.controller.close()
})
Text($r('app.string.confirm')).fontSize(commonConst.DEFAULT_20).fontColor($r('app.color.blueColor'))
.onClick(() => {
this.setFrequency()
this.frequency = this.currentFrequency
this.controller.close()
})
}
.justifyContent(FlexAlign.SpaceAround)
.width(commonConst.THOUSANDTH_900)
.height(commonConst.DEFAULT_28)
.margin({ bottom: commonConst.DEFAULT_16 })
}
.justifyContent(FlexAlign.Center)
.height(commonConst.THOUSANDTH_940)
.padding(commonConst.DEFAULT_12)
}
}
定义频率设置视图模型
// ets/viewModel/FrequencySetting.ets
import { FrequencyContentType } from "../model/TaskInitList"
export function padTo2Digits(num: number) {
return num.toString().padStart(2, '0')
}
const chineseNumOfWeek: string[] = ['一', '二', '三', '四', '五', '六', '日']
const WEEK: string = '星期'
export const frequencyRange = () => {
const frequencyRangeArr: FrequencyContentType[] = []
chineseNumOfWeek.forEach((item: string, index: number) => {
frequencyRangeArr.push({
id: (index + 1),
label: `${WEEK}${item}`,
isChecked: false
})
})
return frequencyRangeArr
}
基础知识:切换按钮 (Toggle)
Toggle组件提供状态按钮样式、勾选框样式和开关样式,一般用于两种状态之间的切换。
创建切换按钮
Toggle通过调用接口来创建,接口调用形式如下:
Toggle(options: { type: ToggleType, isOn?: boolean })
其中,ToggleType为开关类型,包括Button、Checkbox和Switch,isOn为切换按钮的状态。
API version 11开始,Checkbox默认样式由圆角方形变为圆形。
接口调用有以下两种形式:
- 创建不包含子组件的Toggle。
当ToggleType为Checkbox或者Switch时,用于创建不包含子组件的Toggle:
Toggle({ type: ToggleType.Checkbox, isOn: false })
Toggle({ type: ToggleType.Checkbox, isOn: true })
Toggle({ type: ToggleType.Switch, isOn: false })
Toggle({ type: ToggleType.Switch, isOn: true })
- 创建包含子组件的Toggle。
当ToggleType为Button时,只能包含一个子组件,如果子组件有文本设置,则相应的文本内容会显示在按钮上。
Toggle({ type: ToggleType.Button, isOn: false }) {
Text('status button')
.fontColor('#182431')
.fontSize(12)
}.width(100)
Toggle({ type: ToggleType.Button, isOn: true }) {
Text('status button')
.fontColor('#182431')
.fontSize(12)
}.width(100)
自定义样式
- 通过selectedColor属性设置Toggle打开选中后的背景颜色。
Toggle({ type: ToggleType.Button, isOn: true }) {
Text('status button')
.fontColor('#182431')
.fontSize(12)
}.width(100).selectedColor(Color.Pink)
Toggle({ type: ToggleType.Checkbox, isOn: true })
.selectedColor(Color.Pink)
Toggle({ type: ToggleType.Switch, isOn: true })
.selectedColor(Color.Pink)
- 通过switchPointColor属性设置Switch类型的圆形滑块颜色,仅对type为ToggleType.Switch生效。
Toggle({ type: ToggleType.Switch, isOn: false })
.switchPointColor(Color.Pink)
Toggle({ type: ToggleType.Switch, isOn: true })
.switchPointColor(Color.Pink)
添加事件
除支持通用事件外,Toggle还用于选中和取消选中后触发某些操作,可以绑定onChange事件来响应操作后的自定义行为。
Toggle({ type: ToggleType.Switch, isOn: false })
.onChange((isOn: boolean) => {
if(isOn) {
// 需要执行的操作
}
})
案例整理
// ets/pages/toggle/usagePage.ets
@Entry
@Component
struct usagePage {
@State isOn: boolean = true
build() {
Column({ space: 20 }) {
Row() {
Toggle({ type: ToggleType.Checkbox, isOn: false })
Toggle({ type: ToggleType.Checkbox, isOn: true })
}
Row() {
Toggle({ type: ToggleType.Switch, isOn: false })
Toggle({ type: ToggleType.Switch, isOn: true })
}
Row() {
Toggle({ type: ToggleType.Button, isOn: false }) {
Text('status button')
.fontColor('#182431')
.fontSize(12)
}.width(100)
Toggle({ type: ToggleType.Button, isOn: true }) {
Text('status button')
.fontColor('#182431')
.fontSize(12)
}.width(100)
}
Row() {
Toggle({ type: ToggleType.Button, isOn: true }) {
Text('status button')
.fontColor('#182431')
.fontSize(12)
}.width(100).selectedColor(Color.Orange)
Toggle({ type: ToggleType.Checkbox, isOn: true })
.selectedColor(Color.Orange)
Toggle({ type: ToggleType.Switch, isOn: true })
.selectedColor(Color.Orange)
}
Row() {
Toggle({ type: ToggleType.Switch, isOn: false })
.switchPointColor(Color.Orange)
Toggle({ type: ToggleType.Switch, isOn: true })
.switchPointColor(Color.Orange)
}
Row() {
Toggle({ type: ToggleType.Switch, isOn: this.isOn })
.onChange((isOn: boolean) => {
this.isOn = !this.isOn
})
Text(`${this.isOn}`)
}
}
.width('100%')
}
}
场景示例
Toggle用于切换蓝牙开关状态。
// ets/pages/toggle/CasePage.ets
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct CasePage {
@State BOnSt: promptAction.ShowToastOptions = { 'message': 'Bluetooth is on.' }
@State BOffSt: promptAction.ShowToastOptions = { 'message': 'Bluetooth is off.' }
build() {
Column() {
Row() {
Text("Bluetooth Mode")
.height(50)
.fontSize(16)
}
Row() {
Text("Bluetooth")
.height(50)
.padding({ left: 10 })
.fontSize(16)
.textAlign(TextAlign.Start)
.backgroundColor(0xFFFFFF)
Toggle({ type: ToggleType.Switch })
.margin({ left: 200, right: 10 })
.onChange((isOn: boolean) => {
if (isOn) {
promptAction.showToast(this.BOnSt)
} else {
promptAction.showToast(this.BOffSt)
}
})
}
.backgroundColor(0xFFFFFF)
}
.padding(10)
.backgroundColor(0xDCDCDC)
.width('100%')
.height('100%')
}
}
基础知识:学习Picker选择器
CalendarPicker
示例
// ets/pages/picker/CalendarPickerPage.ets
@Entry
@Component
struct CalendarPickerPage {
private selectedDate: Date = new Date('2025-03-05')
build() {
Column() {
Text('月历日期选择器').fontSize(30)
Column() {
CalendarPicker({ hintRadius: 10, selected: this.selectedDate })
.edgeAlign(CalendarAlign.END)
.textStyle({ color: "#182431", font: { size: 20, weight: FontWeight.Normal } })
.margin(10)
.onChange((value) => {
console.info("CalendarPicker onChange:" + JSON.stringify(value))
})
}
.alignItems(HorizontalAlign.End)
.width("100%")
}.width('100%')
}
}
DatePicker
示例
// ets/pages/picker/DatePickerPage.ets
@Entry
@Component
struct DatePickerPage {
@State isLunar: boolean = false
private selectedDate: Date = new Date('2025-08-08')
build() {
Column() {
Button('切换公历农历')
.margin({ top: 30, bottom: 30 })
.onClick(() => {
this.isLunar = !this.isLunar
})
DatePicker({
start: new Date('1970-1-1'),
end: new Date('2100-1-1'),
selected: this.selectedDate
})
.disappearTextStyle({ color: Color.Gray, font: { size: '16fp', weight: FontWeight.Bold } })
.textStyle({ color: '#182431', font: { size: '18fp', weight: FontWeight.Normal } })
.selectedTextStyle({ color: '#0000FF', font: { size: '26fp', weight: FontWeight.Regular } })
.lunar(this.isLunar)
.onDateChange((value: Date) => {
this.selectedDate = value
console.info('select current date is: ' + value.toString())
})
}.width('100%')
}
}
TextPicker
示例1(设置选择器列数)
该示例通过配置range实现单列或多列文本选择器。
// ets/pages/picker/TextPicker01Page.ets
class bottom {
bottom: number = 50
}
let bott: bottom = new bottom()
@Entry
@Component
struct TextPicker01Page {
private select: number = 1
private apFruits: string[] = ['apple1', 'apple2', 'apple3', 'apple4']
private orFruits: string[] = ['orange1', 'orange2', 'orange3', 'orange4']
private peFruits: string[] = ['peach1', 'peach2', 'peach3', 'peach4']
private multi: string[][] = [this.apFruits, this.orFruits, this.peFruits]
private cascade: TextCascadePickerRangeContent[] = [
{
text: '辽宁省',
children: [{ text: '沈阳市', children: [{ text: '沈河区' }, { text: '和平区' }, { text: '浑南区' }] },
{ text: '大连市', children: [{ text: '中山区' }, { text: '金州区' }, { text: '长海县' }] }]
},
{
text: '吉林省',
children: [{ text: '长春市', children: [{ text: '南关区' }, { text: '宽城区' }, { text: '朝阳区' }] },
{ text: '四平市', children: [{ text: '铁西区' }, { text: '铁东区' }, { text: '梨树县' }] }]
},
{
text: '黑龙江省',
children: [{ text: '哈尔滨市', children: [{ text: '道里区' }, { text: '道外区' }, { text: '南岗区' }] },
{ text: '牡丹江市', children: [{ text: '东安区' }, { text: '西安区' }, { text: '爱民区' }] }]
}
]
build() {
Column() {
TextPicker({ range: this.apFruits, selected: this.select })
.onChange((value: string | string[], index: number | number[]) => {
console.info('Picker item changed, value: ' + value + ', index: ' + index)
}).margin(bott)
TextPicker({ range: this.multi })
.onChange((value: string | string[], index: number | number[]) => {
console.info('TextPicker 多列:onChange ' + JSON.stringify(value) + ', ' + 'index: ' + JSON.stringify(index))
}).margin(bott)
TextPicker({ range: this.cascade })
.onChange((value: string | string[], index: number | number[]) => {
console.info('TextPicker 多列联动:onChange ' + JSON.stringify(value) + ', ' + 'index: ' +
JSON.stringify(index))
})
}
}
}
示例2(设置文本样式)
该示例通过配置disappearTextStyle、textStyle、selectedTextStyle实现文本选择器中的文本样式。
// ets/pages/picker/TextPicker02Page.ets
@Entry
@Component
struct TextPicker02Page {
private select: number = 1
private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']
build() {
Column() {
TextPicker({ range: this.fruits, selected: this.select })
.onChange((value: string | string[], index: number | number[]) => {
console.info('Picker item changed, value: ' + value + ', index: ' + index)
})
.disappearTextStyle({ color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } })
.textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } })
.selectedTextStyle({ color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } })
}
.width('100%')
.height('100%')
}
}
示例3(设置无分割线样式)
该示例通过配置divider为null实现无分割线样式的文本选择器。
// ets/pages/picker/TextPicker03Page.ets
@Entry
@Component
struct TextPicker03Page {
private select: number = 1
private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']
build() {
Column() {
TextPicker({ range: this.fruits, selected: this.select })
.onChange((value: string | string[], index: number | number[]) => {
console.info('Picker item changed, value: ' + value + ', index: ' + index)
})
.disappearTextStyle({color: Color.Red, font: {size: 15, weight: FontWeight.Lighter}})
.textStyle({color: Color.Black, font: {size: 20, weight: FontWeight.Normal}})
.selectedTextStyle({color: Color.Blue, font: {size: 30, weight: FontWeight.Bolder}})
.divider(null)
}.width('100%').height('100%')
}
}
示例4(设置分割线样式)
该示例通过配置divider的DividerOptions类型实现分割线样式的文本选择器。
// ets/pages/picker/TextPicker04Page.ets
@Entry
@Component
struct TextPicker04Page {
private select: number = 1
private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']
build() {
Column() {
TextPicker({ range: this.fruits, selected: this.select })
.onChange((value: string | string[], index: number | number[]) => {
console.info('Picker item changed, value: ' + value + ', index: ' + index)
})
.disappearTextStyle({ color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } })
.textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } })
.selectedTextStyle({ color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } })
.divider({
strokeWidth: 10,
color: Color.Red,
startMargin: 10,
endMargin: 20
} as DividerOptions)
}
.width('100%')
.height('100%')
}
}
示例5(设置渐隐效果)
该示例通过gradientHeight自定义TextPicker的渐隐效果高度。
// ets/pages/picker/TextPicker05Page.ets
@Entry
@Component
struct TextPicker05Page {
private select: number = 1
private fruits: string[] = ['apple1', 'orange2', 'peach3', 'grape4']
build() {
Column() {
TextPicker({ range: this.fruits, selected: this.select })
.onChange((value: string | string[], index: number | number[]) => {
console.info('Picker item changed, value: ' + value + ', index: ' + index)
})
.disappearTextStyle({ color: Color.Red, font: { size: 15, weight: FontWeight.Lighter } })
.textStyle({ color: Color.Black, font: { size: 20, weight: FontWeight.Normal } })
.selectedTextStyle({ color: Color.Blue, font: { size: 30, weight: FontWeight.Bolder } })
.gradientHeight(100)
}.width('100%').height('100%')
}
}
TimePicker
示例
// ets/pages/picker/TimePicker.ets
@Entry
@Component
struct TimePickerExample {
@State isMilitaryTime: boolean = false
private selectedTime: Date = new Date('2025-07-22T08:00:00')
build() {
Column() {
Button('切换12小时制/24小时制')
.margin(30)
.onClick(() => {
this.isMilitaryTime = !this.isMilitaryTime
})
TimePicker({
selected: this.selectedTime,
format: TimePickerFormat.HOUR_MINUTE_SECOND
})
.useMilitaryTime(this.isMilitaryTime)
.onChange((value: TimePickerResult) => {
if(value.hour >= 0) {
this.selectedTime.setHours(value.hour, value.minute)
console.info(`${value}`)
}
})
.disappearTextStyle({color: Color.Red, font: {size: 15, weight: FontWeight.Lighter}})
.textStyle({color: Color.Black, font: {size: 20, weight: FontWeight.Normal}})
.selectedTextStyle({color: Color.Blue, font: {size: 30, weight: FontWeight.Bolder}})
}.width('100%')
}
}