1.HarmonyOS开发 弹窗组件
弹窗是移动应用中常见的一种用户界面元素,常用于显示一些重要的信息、提示用户进行操作或收集用户输入。ArkTS提供了多种内置的弹窗供开发者使用,除此之外还支持自定义弹窗,来满足各种不同的需求。
1.1. 示例
1.1.1. 消息提示
Toast(消息提示),常用于显示一些简短的消息或提示,一般会在短暂停留后自动消失。具体效果如下
showToast()方法的参数定义如下
showToast(options: { message: string | Resource,duration?: number,bottom?: string | number})
(1)message
message属性用于设置提示信息
(2) duration
duration属性用于设置提示信息停留时长,单位为毫秒,取值范围是[1500,10000]
(3) bottom
bottom属性用于设置提示信息到底部的距离
private toastClick() {
promptAction.showToast({
message: '吐司',
duration: 2000,
bottom: 50
});
}
1.1.2. 警告对话框
AlertDialog(警告对话框)用于向用户发出警告或确认操作的提示,确保用户在敏感操作前进行确认。具体效果如下
/**
* 警告对话框
*/
private alertClick() {
AlertDialog.show(
{
title: '删除该记录?', //弹窗标题
message: '删除后无法恢复,您确认要删除吗?', //弹窗信息
autoCancel: true, //点击遮障层时,是否关闭弹窗
alignment: DialogAlignment.Center, //弹窗位置
offset: { dx: 0, dy: -20 }, //相对于弹窗位置的偏移量
primaryButton: { //主要按钮,位于左侧
value: '确认', //按钮内容
fontColor: Color.Red, //字体颜色
action: () => { //点击回调
console.log('确认删除')
}
},
secondaryButton: { //次要按钮,位于右侧
value: '取消',
action: () => {
console.log('取消删除')
}
},
cancel: () => { //点击遮罩层取消时的回调
console.info('Closed callbacks')
}
}
)
}
1.1.3. 操作列表弹框
ActionSheet(操作列表弹窗)用于提供一组选项给用户选择,用户从中选择后,可执行相应的操作。具体效果如下
可使用全局方法ActionSheet.show()显示操作列表弹窗
/**
* 操作弹窗
*/
private operaClick() {
ActionSheet.show({
title: '文件操作', //弹窗标题
message: '请选择你要对该文件执行的操作', //弹窗内容
autoCancel: true, //点击遮障层时,是否关闭弹窗
alignment: DialogAlignment.Center, //弹窗位置
offset: { dx: 0, dy: -20 }, //弹窗相对alignment位置的偏移量
confirm: { //底部按钮
value: '取消', //按钮文本内容
action: () => { //按钮回调函数
console.log('点击按钮取消')
}
},
// cancel: () => { //点击遮障层关闭弹窗时的回调
// console.log('点击遮障层取消')
// },
sheets: [ //操作选项列表
{
icon: $r('app.media.icon_my_config'), //图标
title: '复制', //文本
action: () => { //回调
console.log('复制文件')
}
},
{
icon: $r('app.media.icon_my_config'),
title: '剪切',
action: () => {
console.log('剪切文件')
}
},
{
icon: $r('app.media.icon_my_config'),
title: '删除',
action: () => {
console.log('删除文件')
}
}
]
})
}
1.1.4. 选择器弹窗
选择器弹窗用于让用户从一个列表中选择一个具体的值。ArkTS内置了多种选择器弹窗,例如文本选择器、日期选择器、时间选择器等等,各选择器效果如下
TextPickerDialog(文本滑动选择器弹窗)
// 是否显示加载框
private isShowLoadingDialog = true
fruits: string[] = ['苹果', '橘子', '香蕉', '鸭梨', '西瓜']
/**
* 选择器弹窗
*/
private selectClick() {
TextPickerDialog.show({
range: this.fruits, //设置文本选择器的选择范围
selected: this.selectedIndex, //设置选中的索引
onAccept: (value: TextPickerResult) => {
//确定按钮的回调函数
// this.selectedIndex = value.index;
},
onCancel: () => { //取消按钮的回调函数
console.info('取消选择')
},
onChange: (value: TextPickerResult) => { //选择器选中内容发生变化时触发的回调函数
console.info(`当前文本:${JSON.stringify(value)}`)
}
})
}
1.1.5. 日期滑动选择弹窗
DatePickerDialog
@State date: Date = new Date("2010-1-1");
/**
* 选择器日期弹窗
*/
private datePickerClick() {
DatePickerDialog.show({
start: new Date("2000-1-1"), //设置选择器的其实日期
end: new Date("2100-12-31"), //设置选择器的结束日期
selected: this.date, //设置当前选中的日期
onAccept: (value: DatePickerResult) => { //确定按钮的回调
this.date.setFullYear(value.year, value.month, value.day)
},
onCancel: () => { //取消按钮的回调
console.info('取消选择')
},
onChange: (value: DatePickerResult) => { //选择器当前内容发生变化时触发的回调函数
console.info(`当前日期:${JSON.stringify(value)}`)
}
})
}
1.1.6. 时间滑动选择期弹窗
TimePickerDialog
@State time: Date = new Date('2020-01-01T00:00:00')
/**
* 选择器时间弹窗
*/
private timePickerClick() {
TimePickerDialog.show({
selected: this.time, //设置当前选中的时间
useMilitaryTime: true, //是否使用24小时制
onAccept: (value: TimePickerResult) => { //确认按钮的回调
this.time.setHours(value.hour, value.minute);
},
onCancel: () => { //取消按钮的回调
console.info('取消选择')
},
onChange: (value: TimePickerResult) => { //选择器当前内容发生变化时触发的回调函数
console.info(`当前时间:${JSON.stringify(value)}`)
}
})
}
1.1.7. 自定义弹窗
当现有组件不满足要求时,可考虑自定义弹窗,自定义弹窗允许开发者自定义弹窗内容和样式。例如
@CustomDialog
struct TextInputDialog {
controller: CustomDialogController =
new CustomDialogController(
{ builder: TextInputDialog() })
// confirm: (value: string) => void;
value: string = '';
build() {
Column({ space: 20 }) {
Text('请输入你的答案')
TextInput({ placeholder: '请输入数字' })
.type(InputType.Number)
.onChange((value) => {
this.value = value;
})
Row({ space: 50 }) {
Button('取消')
.onClick(() => {
this.controller.close();
})
Button('确认').onClick(() => {
// this.confirm(this.value);
this.controller.close();
})
}
}.padding(20)
}
}
@State answer: string = '?'
controller: CustomDialogController =
new CustomDialogController({
builder: TextInputDialog({
// confirm: (value) => {
// this.answer = value;
// }
}),
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -30 }
})
/**
* 自定义弹窗
*/
private customDialogClick() {
this.controller.open();
}
1.2. 完整代码
import { promptAction, router } from '@kit.ArkUI'
import { TitleBar } from '../../components/common/TitleBar'
import { RouterParams } from '../../helper/RouterHelper'
import { LoadingDialog } from '../../components/dialog/LoadingDialog'
@Extend(Button)
function buttonItem() {
.stateEffect(true)
.type(ButtonType.Normal)
.borderRadius(8)
.fontSize(17)
.backgroundColor($r('app.color.primary_green'))
.padding({
top: 8,
bottom: 8,
left: 70,
right: 70
})
.margin({
top: 8,
bottom: 8
})
}
@Entry
@Component
struct ToastPage {
@State pageTitle: string = "弹出框"
// 加载框
private loadingDialog: CustomDialogController = new
CustomDialogController({
builder: LoadingDialog(),
customStyle: true
})
// 是否显示加载框
private isShowLoadingDialog = true
fruits: string[] = ['苹果', '橘子', '香蕉', '鸭梨', '西瓜']
@State date: Date = new Date("2010-1-1");
@State time: Date = new Date('2020-01-01T00:00:00')
@State selectedIndex: number = 0
@State answer: string = '?'
controller: CustomDialogController =
new CustomDialogController({
builder: TextInputDialog({
// confirm: (value) => {
// this.answer = value;
// }
}),
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -30 }
})
aboutToAppear() {
try {
this.pageTitle = (router
.getParams() as RouterParams).title
} catch (e) {
}
}
/**
* Toast(消息提示),常用于显示一些简短的消息或提示,
* 一般会在短暂停留后自动消失。
*showToast(options: { message: string |
* Resource,duration?: number,bottom?: string | number})
* message属性用于设置提示信息
*duration属性用于设置提示信息停留时长,单位为毫秒,取值范围是[1500,10000]
*bottom属性用于设置提示信息到底部的距离
*/
private toastClick() {
promptAction.showToast({
message: '吐司',
duration: 2000,
bottom: 50
});
}
/**
* 弹窗
*/
private popClick() {
AlertDialog.show(
{
title: '标题',
message: '内容',
autoCancel: true,//点击外侧是否关闭
alignment: DialogAlignment.Center,
offset: { dx: 0, dy: -20 },
gridCount: 3,
confirm: {
value: '确定',
action: () => {
console.info('==ewcallback')
}
},
cancel: () => {
console.info('==ewClosed callbacks')
}
}
)
}
/**
* 弹窗2
*/
private pop2Click() {
AlertDialog.show(
{
title: '标题',
message: '内容',
autoCancel: true,//点击外侧是否关闭
alignment: DialogAlignment.Center,
gridCount: 4,
offset: { dx: 0, dy: -20 },
primaryButton: {
value: '取消',
action: () => {
console.info('==ew==取消')
}
},
secondaryButton: {
value: '确定',
action: () => {
console.info('==ew==确定')
}
},
cancel: () => {
console.info('==ew==点击外侧关闭')
}
}
)
}
/**
* 操作弹窗
*/
private operaClick() {
ActionSheet.show({
title: '文件操作', //弹窗标题
message: '请选择你要对该文件执行的操作', //弹窗内容
autoCancel: true, //点击遮障层时,是否关闭弹窗
alignment: DialogAlignment.Center, //弹窗位置
offset: { dx: 0, dy: -20 }, //弹窗相对alignment位置的偏移量
confirm: { //底部按钮
value: '取消', //按钮文本内容
action: () => { //按钮回调函数
console.log('点击按钮取消')
}
},
// cancel: () => { //点击遮障层关闭弹窗时的回调
// console.log('点击遮障层取消')
// },
sheets: [ //操作选项列表
{
icon: $r('app.media.icon_my_config'), //图标
title: '复制', //文本
action: () => { //回调
console.log('复制文件')
}
},
{
icon: $r('app.media.icon_my_config'),
title: '剪切',
action: () => {
console.log('剪切文件')
}
},
{
icon: $r('app.media.icon_my_config'),
title: '删除',
action: () => {
console.log('删除文件')
}
}
]
})
}
/**
* 加载弹窗
*/
private loadingClick() {
if (this.isShowLoadingDialog) {
// 显示加载框
this.loadingDialog.open()
} else {
// 关闭加载框
this.loadingDialog.close()
}
this.isShowLoadingDialog = !this.isShowLoadingDialog
}
/**
* 选择器弹窗
*/
private selectClick() {
TextPickerDialog.show({
range: this.fruits, //设置文本选择器的选择范围
selected: this.selectedIndex, //设置选中的索引
onAccept: (value: TextPickerResult) => {
//确定按钮的回调函数
// this.selectedIndex = value.index;
},
onCancel: () => { //取消按钮的回调函数
console.info('取消选择')
},
onChange: (value: TextPickerResult) => { //选择器选中内容发生变化时触发的回调函数
console.info(`当前文本:${JSON.stringify(value)}`)
}
})
}
/**
* 选择器日期弹窗
*/
private datePickerClick() {
DatePickerDialog.show({
start: new Date("2000-1-1"), //设置选择器的其实日期
end: new Date("2100-12-31"), //设置选择器的结束日期
selected: this.date, //设置当前选中的日期
onAccept: (value: DatePickerResult) => { //确定按钮的回调
this.date.setFullYear(value.year, value.month, value.day)
},
onCancel: () => { //取消按钮的回调
console.info('取消选择')
},
onChange: (value: DatePickerResult) => { //选择器当前内容发生变化时触发的回调函数
console.info(`当前日期:${JSON.stringify(value)}`)
}
})
}
/**
* 选择器时间弹窗
*/
private timePickerClick() {
TimePickerDialog.show({
selected: this.time, //设置当前选中的时间
useMilitaryTime: true, //是否使用24小时制
onAccept: (value: TimePickerResult) => { //确认按钮的回调
this.time.setHours(value.hour, value.minute);
},
onCancel: () => { //取消按钮的回调
console.info('取消选择')
},
onChange: (value: TimePickerResult) => { //选择器当前内容发生变化时触发的回调函数
console.info(`当前时间:${JSON.stringify(value)}`)
}
})
}
/**
* 自定义弹窗
*/
private customDialogClick() {
this.controller.open();
}
/**
* 警告对话框
*/
private alertClick() {
AlertDialog.show(
{
title: '删除该记录?', //弹窗标题
message: '删除后无法恢复,您确认要删除吗?', //弹窗信息
autoCancel: true, //点击遮障层时,是否关闭弹窗
alignment: DialogAlignment.Center, //弹窗位置
offset: { dx: 0, dy: -20 }, //相对于弹窗位置的偏移量
primaryButton: { //主要按钮,位于左侧
value: '确认', //按钮内容
fontColor: Color.Red, //字体颜色
action: () => { //点击回调
console.log('确认删除')
}
},
secondaryButton: { //次要按钮,位于右侧
value: '取消',
action: () => {
console.log('取消删除')
}
},
cancel: () => { //点击遮罩层取消时的回调
console.info('Closed callbacks')
}
}
)
}
build() {
Column() {
TitleBar({ pageTitle: $pageTitle })
Button('吐司')
.buttonItem()
.onClick(this.toastClick)
Button('弹窗')
.buttonItem()
.onClick(this.popClick)
Button('弹窗2')
.buttonItem()
.onClick(this.pop2Click)
Button('加载弹窗')
.buttonItem()
.onClick(() => this.loadingClick())
Button('警告对话框')
.buttonItem()
.onClick(() => this.alertClick())
Button('操作对话框')
.buttonItem()
.onClick(() => this.operaClick())
Button('选择器弹窗')
.buttonItem()
.onClick(() => this.selectClick())
Button('选择器日期弹窗')
.buttonItem()
.onClick(() => this.timePickerClick())
Button('选择器时间弹窗')
.buttonItem()
.onClick(() => this.timePickerClick())
Button('自定义弹窗')
.buttonItem()
.onClick(() => this.customDialogClick())
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
}
}
@CustomDialog
struct TextInputDialog {
controller: CustomDialogController =
new CustomDialogController(
{ builder: TextInputDialog() })
// confirm: (value: string) => void;
value: string = '';
build() {
Column({ space: 20 }) {
Text('请输入你的答案')
TextInput({ placeholder: '请输入数字' })
.type(InputType.Number)
.onChange((value) => {
this.value = value;
})
Row({ space: 50 }) {
Button('取消')
.onClick(() => {
this.controller.close();
})
Button('确认').onClick(() => {
// this.confirm(this.value);
this.controller.close();
})
}
}.padding(20)
}
}