【HarmonyOS开发】ArkUI中的自定义弹窗

弹窗是一种模态窗口,通常用来展示用户当前需要的或用户必须关注的信息或操作。在弹出框消失之前,用户无法操作其他界面内容。ArkUI 为我们提供了丰富的弹窗功能,弹窗按照功能可以分为以下两类:

  • 确认类:例如警告弹窗 AlertDialog。
  • 选择类:包括文本选择弹窗 TextPickerDialog 、日期滑动选择弹窗 DatePickerDialog、时间滑动选择弹窗 TimePickerDialog 等。

可以根据业务场景,选择不同类型的弹窗。

1、什么是自定义弹窗?

自定义弹窗的使用更加灵活,适用于更多的业务场景,在自定义弹窗中您可以自定义弹窗内容,构建更加丰富的弹窗界面。自定义弹窗的界面可以通过装饰器@CustomDialog 定义的组件来实现,然后结合 CustomDialogController 来控制自定义弹窗的显示和隐藏。

2、定义自定义弹窗

复制代码
@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 })
    }
  }
}

3、使用自定义弹窗

复制代码
@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%')
}

4、一个完整的示例(常用网站选择)

复制代码
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%')
  }
}

为了能让大家更好的学习鸿蒙 (OpenHarmony) 开发技术,这边特意整理了《鸿蒙 (OpenHarmony)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙 (OpenHarmony)开发学习手册》

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. ......

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门?:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ......

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ......

基于ArkTS 开发:https://qr21.cn/FV7h05

1.Ability开发

2.UI开发

3.公共事件与通知

4.窗口管理

5.媒体

6.安全

7.网络与链接

8.电话服务

9.数据管理

10.后台任务(Background Task)管理

11.设备管理

12.设备使用信息统计

13.DFX

14.国际化开发

15.折叠屏系列

16.......

相关推荐
zhujian826375 分钟前
二十七、【鸿蒙 NEXT】如何实时查看数据库
数据库·华为·harmonyos·查看数据库
恋猫de小郭9 分钟前
Flutter 又迎大坑修改?iOS 26 键盘变化可能带来大量底层改动
android·flutter·ios·kotlin
e***985715 分钟前
PHP下载站开发全攻略
android
lbb 小魔仙15 分钟前
【Harmonyos】开源鸿蒙跨平台训练营DAY1:Windows上搭建Flutte跨平台开发环境
windows·flutter·harmonyos·鸿蒙·开源鸿蒙·鸿蒙开平台应用
胖虎122 分钟前
从一个自定义的下载Dialog,说清 Android 自定义弹窗的关键点。
android·dialog·gitee·自定义弹窗
UrSpecial25 分钟前
IM项目——用户管理子服务
android·adb
猛扇赵四那边好嘴.29 分钟前
Flutter 框架跨平台鸿蒙开发 - 数学练习应用开发教程
flutter·华为·harmonyos
[H*]35 分钟前
Flutter框架跨平台鸿蒙开发——Image Providers详解
flutter·华为·harmonyos
熊猫钓鱼>_>1 小时前
【开源鸿蒙跨平台开发先锋训练营】DAY 2 React Native for OpenHarmony 开发笔记与实战指南
react native·开源·harmonyos·arkts·openharmony·gitcode·atomgit
不会Android的潘潘1 小时前
adb指令扩展方案
android·adb·aosp