弹窗的使用
场景说明
应用中经常用到弹窗,比如警告弹窗、日期选择弹窗、文本选择弹窗以及其他自定义弹窗等等。本例将为大家介绍如何使用不同的弹窗。
效果呈现
本例最终效果如下:

示例中共涉及四类弹窗:
- 警告弹窗:提示信息尚未保存。
- 日期滑动选择器弹窗:选择出生日期。
- 文本滑动选择器弹窗:选择性别。
- 自定义弹窗:填写兴趣爱好。
说明:
自定义弹窗可以根据业务需要自行定义弹窗的形式和内容,比如文本输入、单选、多选等等,本例以文本输入为例进行介绍。
运行环境
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
- IDE: DevEco Studio 3.1 Release
- SDK: Ohos_sdk_public 3.2.12.5(API Version 9 Release)
实现思路
本例中涉及的4类弹窗及实现方案如下:
- 警告弹窗:使用AlertDialog实现。
- 日期滑动选择器弹窗:使用DatePickerDialog实现。
- 文本滑动选择器弹窗:使用TextPickerDialog实现。
- 自定义弹窗:使用CustomDialogController实现。
开发步骤
由于本例重点讲解对话框的使用,所以开发步骤会着重讲解相关实现,不相关的内容不做介绍,全量代码可参考完整代码章节。
-
首先,使用AlertDialog实现警告弹窗。
通过message参数设置告警信息,alignment设置弹窗在界面中垂直方向的对齐方式;通过primaryButton和secondaryButton添加按钮。
具体代码如下:
-
使用DatePickerDialog实现日期滑动选择器弹窗。
通过start和end分别设置日期区间的起始时间和末尾时间;通过lunar设置使用农历还是阳历;使用onAccept监听选择的日期,本例中通过变量selectedDate将选中的日期设置给参数selected,这样弹窗弹出时的日期就默认为上次选中的日期。
具体代码如下:
-
使用TextPickerDialog实现文本滑动选择器弹窗。
通过range设置文本选择项,使用onAccept监听选择的文本项,本例中通过变量selectedGender将选中的性别的索引设置给参数selected,这样弹窗弹出时的性别就默认为上次选中的性别。
具体代码如下:
-
使用CustomDialogController实现自定义弹窗。
当现有弹窗不能满足业务诉求时,开发者可以自行设计弹窗的样式。在实现自定义弹窗时,需要将弹窗的UI放在被@CustomDialog修饰的自定义组件中,然后使用CustomDialogController的实例来控制弹窗的弹出和关闭。
具体代码如下:
完整代码
本例完整代码如下:
import Context from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
@Component
struct TextFrame{
@Link content: string;
private textImage:Resource;
private text:string;
onTextClick:()=>void;
build(){
Row(){
Image(this.textImage)
.width(24)
.height(24)
.margin({left:12})
Text(this.text)
.fontSize(16)
.margin({ left:12 })
.height(24)
Text(this.content)
.fontSize(16)
.textAlign(TextAlign.End)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.margin({
left: 16,
right: 7
})
.layoutWeight(1)
.width('100%')
Image($r('app.media.ic_arrow'))
.width(12)
.height(24)
.margin({ right: 14 })
}
.margin({ top: 24 })
.borderRadius(24)
.backgroundColor(Color.White)
.width('93.3%')
.height(64)
.onClick(this.onTextClick)
}
}
@Component
struct InputFrame{
private inputImage: Resource;
private hintText: string;
build(){
Row() {
Image(this.inputImage)
.width(24)
.height(24)
.margin({ left: 12 })
TextInput({ placeholder: this.hintText })
.fontSize(16)
.padding({ left: 12 })
.placeholderColor('#99000000')
.backgroundColor(Color.White)
.fontWeight(FontWeight.Normal)
.fontStyle(FontStyle.Normal)
.fontColor(Color.Black)
.margin({ right: 32 })
.layoutWeight(1)
.height(48)
}
.margin({ top: 24 })
.borderRadius(24)
.backgroundColor(Color.White)
.width('93.3%')
.height(64)
}
}
@CustomDialog
struct CustomDialogFrame{
@Link textValue: string
@Link inputValue: string
controller: CustomDialogController
build(){
Column() {
Text('兴趣爱好').fontSize(20).margin({ top: 10, bottom: 10 })
TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%')
.onChange((value: string) => {
this.textValue = value
})
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('取消')
.onClick(() => {
this.controller.close()
}).backgroundColor('').fontColor('#007DFF')
Button('保存')
.onClick(() => {
this.inputValue = this.textValue
this.controller.close()
}).backgroundColor(0xffffff).fontColor('#007DFF')
}.margin({ bottom: 10 })
}.justifyContent(FlexAlign.Start)
}
}
@Entry
@Component
struct Index {
@State birthdate: string = '';
@State sex: string = '';
@State textValue: string = '';
@State inputValue: string = '';
selectedDate: Date = new Date("2010-1-1")
selectedGender:number = 0
private sexArray: Resource = $r('app.strarray.sex_array');
customDialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogFrame({
textValue: $textValue,
inputValue: $inputValue
}),
alignment: DialogAlignment.Bottom,
offset: {
dx: 0,
dy: -20
}
});
alertDialog(context: Context.UIAbilityContext) {
AlertDialog.show({
message: '当前数据未保存,是否确认离开?',
alignment: DialogAlignment.Bottom,
offset: {
dx: 0,
dy: -20
},
primaryButton: {
value: '取消',
action: () => {
console.info('Callback cancel button is clicked');
}
},
secondaryButton: {
value: '确定',
action: () => {
// Exiting the app.
context.terminateSelf();
console.info('Callback definite button is clicked');
}
}
});
}
datePickerDialog(dateCallback) {
DatePickerDialog.show({
start: new Date('1900-1-1'),
end: new Date('2100-1-1'),
selected: this.selectedDate,
lunar: false,
onAccept: (value: DatePickerResult) => {
let year = value.year;
let month = value.month + 1;
let day = value.day;
let birthdate: string = this.getBirthDateValue(year, month, day);
this.selectedDate.setFullYear(value.year, value.month, value.day)
dateCallback(birthdate);
}
});
}
textPickerDialog(sexArray: Resource, sexCallback) {
if (this.isEmptyArr(sexArray)) {
console.error('sex is null');
return;
}
TextPickerDialog.show({
range: sexArray,
selected: this.selectedGender,
onAccept: (result: TextPickerResult) => {
sexCallback(result.value);
this.selectedGender = result.index
},
onCancel: () => {
console.info('TextPickerDialog onCancel');
}
});
}
getBirthDateValue(year: number, month: number, day: number): string {
let birthdate: string = `${year}${'年'}${month}` +
`${'月'}${day}${'日'}`;
return birthdate;
}
isEmpty(obj): boolean {
return obj === undefined || obj === null || obj === '';
}
isEmptyArr(array): boolean {
return this.isEmpty(array) || array.length === 0;
}
build() {
Row() {
Column() {
Row(){
Image($r('app.media.ic_back'))
.width(26)
.height(26)
.alignSelf(ItemAlign.Start)
.margin({
left: '7.2%',
top: 19
})
.onClick(() => {
let context = getContext(this) as Context.UIAbilityContext;
this.alertDialog(context);
})
Text('个人信息')
.fontColor(Color.Black)
.fontSize(20)
.margin({ top: 20,left:20 })
.alignSelf(ItemAlign.Center)
}.width('100%')
Image($r('app.media.ic_avatar'))
.width(56)
.height(56)
.alignSelf(ItemAlign.Center)
.margin({ top: '5.5%' })
Text('头像')
.fontColor(Color.Black)
.fontSize(16)
.margin({ top: '2.1%' })
.alignSelf(ItemAlign.Center)
InputFrame({
inputImage: $r('app.media.ic_nickname'),
hintText: '昵称'
})
TextFrame({
textImage: $r('app.media.ic_birthdate'),
text: '出生日期',
content: $birthdate,
onTextClick: () => {
this.datePickerDialog((birthValue: string) => {
this.birthdate = birthValue;
});
}
})
TextFrame({
textImage: $r('app.media.ic_sex'),
text: '性别',
content: $sex,
onTextClick: () => {
this.textPickerDialog(this.sexArray, (sexValue: string) => {
this.sex = sexValue;
});
}
})
InputFrame({
inputImage: $r('app.media.ic_signature'),
hintText: '个性签名'
})
TextFrame({
textImage: $r('app.media.ic_hobbies'),
text: '兴趣爱好',
content: $textValue,
onTextClick: () => {
this.customDialogController.open();
}
})
}
.backgroundColor('#F5F5F5')
.height('100%')
.width('100%')
}
.height('100%')
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
参考