弹窗是一种模态窗口,通常用来展示用户当前需要的或用户必须关注的信息或操作。在弹出框消失之前,用户无法操作其他界面内容。ArkUI 为我们提供了丰富的弹窗功能,弹窗按照功能可以分为以下两类:
确认类:例如警告弹窗 AlertDialog。
选择类:包括文本选择弹窗 TextPickerDialog 、日期滑动选择弹窗 DatePickerDialog、时间滑动选择弹窗 TimePickerDialog 等。
您可以根据业务场景,选择不同类型的弹窗。
参考:OpenHarmony 弹窗文档V4.0
今天我们主要了解一下自定义弹窗的使用
自定义弹窗
自定义弹窗的使用更加灵活,适用于更多的业务场景,在自定义弹窗中您可以自定义弹窗内容,构建更加丰富的弹窗界面。自定义弹窗的界面可以通过装饰器@CustomDialog 定义的组件来实现,然后结合 CustomDialogController 来控制自定义弹窗的显示和隐藏。
1、定义自定义弹窗
@CustomDialog
struct CustomDialogExample {
// 双向绑定传值
@Prop title: string
@Link inputValue: string
// 弹窗控制器,控制打开/关闭,必须传入,且名称必须为:controller
controller: CustomDialogController
// 弹窗中的按钮事件
cancel: () => void
confirm: () => void
// 弹窗中的内容描述
build() {
Column() {
Text(this.title || "是否修改文本框内容?")
.fontSize(16)
.margin(24)
.textAlign(TextAlign.Start)
.width("100%")
TextInput({
placeholder: '文本输入框',
text: this.inputValue
})
.height(60)
.width('90%')
.onChange((value: string) => {
this.textValue = value
})
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('取消')
.onClick(() => {
this.controller.close()
this.cancel()
}).backgroundColor(0xffffff).fontColor(Color.Black)
Button('确定')
.onClick(() => {
this.controller.close()
this.confirm()
}).backgroundColor(0xffffff).fontColor(Color.Red)
}.margin({ bottom: 10 })
}
}
}
2、使用自定义弹窗
@Entry
@Component
struct Index {
@State title: string = '标题'
@State inputValue: string = '文本框父子组件数据双绑'
// 定义自定义弹窗的Controller,传入参数和回调函数
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({
cancel: this.onCancel,
confirm: this.onAccept,
textValue: $textValue,
inputValue: $inputValue
}),
cancel: this.existApp,
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -20 },
gridCount: 4,
customStyle: false
})
aboutToDisappear() {
this.dialogController = undefined // 将dialogController置空
}
onCancel() {
console.info('点击取消按钮', this.inputValue)
}
onAccept() {
console.info('点击确认按钮', this.inputValue)
}
build() {
Column() {
Button('打开自定义弹窗')
.width('60%')
.margin({top:320})
.zIndex(999)
.onClick(()=>{
if (this.dialogController != undefined) {
this.dialogController.open()
}
})
}
.height('100%')
.width('100%')
}
3、一个完整的示例(常用网站选择)
export interface HobbyBean {
label: string;
isChecked: boolean;
}
export type DataItemType = { value: string }
@Extend(Button) function dialogButtonStyle() {
.fontSize(16)
.fontColor("#007DFF")
.layoutWeight(1)
.backgroundColor(Color.White)
.width(500)
.height(40)
}
@CustomDialog
struct CustomDialogWidget {
@State hobbyBeans: HobbyBean[] = [];
@Prop title:string;
@Prop hobbyResult: Array<DataItemType>;
@Link hobbies: string;
private controller: CustomDialogController;
setHobbiesValue(hobbyBeans: HobbyBean[]) {
let hobbiesText: string = '';
hobbiesText = hobbyBeans.filter((isCheckItem: HobbyBean) =>
isCheckItem?.isChecked)
.map((checkedItem: HobbyBean) => {
return checkedItem.label;
}).join(',');
this.hobbies = hobbiesText;
}
aboutToAppear() {
// let context: Context = getContext(this);
// let manager = context.resourceManager;
// manager.getStringArrayValue($r('app.strarray.hobbies_data'), (error, hobbyResult) => {
// });
this.hobbyResult.forEach(item => {
const hobbyBean = {
label: item.value,
isChecked: this.hobbies.includes(item.value)
}
this.hobbyBeans.push(hobbyBean);
});
}
build() {
Column() {
Text(this.title || "兴趣爱好")
.fontWeight(FontWeight.Bold)
.alignSelf(ItemAlign.Start)
.margin({ left: 24, bottom: 12 })
List() {
ForEach(this.hobbyBeans, (itemHobby: HobbyBean) => {
ListItem() {
Row() {
Text(itemHobby.label)
.fontSize(16)
.fontColor("#182431")
.layoutWeight(1)
.textAlign(TextAlign.Start)
.fontWeight(500)
.margin({ left: 24 })
Toggle({ type: ToggleType.Checkbox, isOn: itemHobby.isChecked })
.margin({
right: 24
})
.onChange((isCheck) => {
itemHobby.isChecked = isCheck;
})
}
}
.height(36)
}, itemHobby => itemHobby.label)
}
.margin({
top: 6,
bottom: 8
})
.divider({
strokeWidth: 0.5,
color: "#0D182431"
})
.listDirection(Axis.Vertical)
.edgeEffect(EdgeEffect.None)
.width("100%")
// .height(248)
Row({
space: 20
}) {
Button("关闭")
.dialogButtonStyle()
.onClick(() => {
this.controller.close();
})
Blank()
.backgroundColor("#F2F2F2")
.width(1)
.opacity(1)
.height(25)
Button("保存")
.dialogButtonStyle()
.onClick(() => {
this.setHobbiesValue(this.hobbyBeans);
this.controller.close();
})
}
}
.width("93.3%")
.padding({
top: 14,
bottom: 16
})
.borderRadius(32)
.backgroundColor(Color.White)
}
}
@Entry
@Component
struct HomePage {
@State hobbies: string = '';
@State hobbyResult: Array<DataItemType> = [
{
"value": "FaceBook"
},
{
"value": "Google"
},
{
"value": "Instagram"
},
{
"value": "Twitter"
},
{
"value": "Linkedin"
}
]
private title: string = '常用网站'
customDialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogWidget({
hobbies: $hobbies,
hobbyResult: this.hobbyResult,
title: this.title
}),
alignment: DialogAlignment.Bottom,
customStyle: true,
offset: { dx: 0,dy: -20 }
});
build() {
Column() {
Button('打开自定义弹窗')
.width('60%')
.margin({top: 50})
.zIndex(999)
.onClick(()=>{
if (this.customDialogController != undefined) {
this.customDialogController.open()
}
})
Text(this.hobbies).fontSize(16).padding(24)
}
.width('100%')
}
}
参考:https://gitee.com/harmonyos/codelabs/tree/master/MultipleDialog