HarmonyOS 鸿蒙Next开发案例 | 弹窗的使用示例包括警告弹窗/日期选择弹窗/文本滑动弹窗/自定义弹窗

HarmonyOS 鸿蒙Next开发案例 | 弹窗的使用示例包括警告弹窗/日期选择弹窗/文本滑动弹窗/自定义弹窗

场景说明

应用中经常用到弹窗,比如警告弹窗、日期选择弹窗、文本选择弹窗以及其他自定义弹窗等等。本例将为大家介绍如何使用不同的弹窗。

效果呈现

本例最终效果如下:

示例动图

示例中共涉及四类弹窗:

  • 警告弹窗:提示信息尚未保存。
  • 日期滑动选择器弹窗:选择出生日期。
  • 文本滑动选择器弹窗:选择性别。
  • 自定义弹窗:填写兴趣爱好。

说明:

自定义弹窗可以根据业务需要自行定义弹窗的形式和内容,比如文本输入、单选、多选等等,本例以文本输入为例进行介绍。

运行环境

本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:

  • IDE: DevEco Studio 3.1.1 Release
  • SDK: 3.1.0(API 9)

实现思路

本例中涉及的4类弹窗及实现方案如下:

  • 警告弹窗:使用AlertDialog实现。
  • 日期滑动选择器弹窗:使用DatePickerDialog实现。
  • 文本滑动选择器弹窗:使用TextPickerDialog实现。
  • 自定义弹窗:使用CustomDialogController实现。

开发步骤

由于本例重点讲解对话框的使用,所以开发步骤会着重讲解相关实现,不相关的内容不做介绍,全量代码可参考完整代码章节。

  1. 首先,使用AlertDialog实现警告弹窗。

    通过message参数设置告警信息,alignment设置弹窗在界面中垂直方向的对齐方式;通过primaryButton和secondaryButton添加按钮。

    具体代码如下:

    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');
          }
        }
      });
    }
    
  2. 使用DatePickerDialog实现日期滑动选择器弹窗。

    通过start和end分别设置日期区间的起始时间和末尾时间;通过lunar设置使用农历还是阳历;使用onAccept监听选择的日期,本例中通过变量selectedDate将选中的日期设置给参数selected,这样弹窗弹出时的日期就默认为上次选中的日期。

    具体代码如下:

    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);
        }
      });
    }
    
  3. 使用TextPickerDialog实现文本滑动选择器弹窗。

    通过range设置文本选择项,使用onAccept监听选择的文本项,本例中通过变量selectedGender将选中的性别的索引设置给参数selected,这样弹窗弹出时的性别就默认为上次选中的性别。

    具体代码如下:

    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');
        }
      });
    }
    
  4. 使用CustomDialogController实现自定义弹窗。

    当现有弹窗不能满足业务诉求时,开发者可以自行设计弹窗的样式。在实现自定义弹窗时,需要将弹窗的UI放在被@CustomDialog修饰的自定义组件中,然后使用CustomDialogController的实例来控制弹窗的弹出和关闭。

    具体代码如下:

    @CustomDialog
    struct CustomDialogFrame{
      ...
      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)
      }
    }
    
    ...
      customDialogController: CustomDialogController = new CustomDialogController({
        builder: CustomDialogFrame({
          textValue: $textValue,
          inputValue: $inputValue
        }),
        alignment: DialogAlignment.Bottom,
        offset: {
          dx: 0,
          dy: -20
        }
      });
    ...
    

完整代码

本例完整代码如下:

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%')
 }
}

参考


更多关于HarmonyOS 鸿蒙Next开发案例 | 弹窗的使用示例包括警告弹窗/日期选择弹窗/文本滑动弹窗/自定义弹窗的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next开发案例 | 弹窗的使用示例包括警告弹窗/日期选择弹窗/文本滑动弹窗/自定义弹窗的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


姓名: 张三
职业: 软件工程师
城市: 北京
工作经验: 5年

技能:

  • Python
  • Java
  • C++

项目经验:

  • 项目一
  • 项目二
回到顶部