【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.......

相关推荐
廖松洋(Alina)1 天前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙
廖松洋(Alina)1 天前
【收尾以及复盘】flutter开发鸿蒙APP之打卡日历页面
flutter·华为·开源·harmonyos·鸿蒙
廖松洋(Alina)1 天前
【收尾以及复盘】flutter开发鸿蒙APP之本月数据统计页面
flutter·华为·开源·harmonyos·鸿蒙
果粒蹬i1 天前
【HarmonyOS】DAY8:React Native for OpenHarmony 实战:多端响应式布局与高可用交互设计
react native·交互·harmonyos
讯方洋哥1 天前
HarmonyOS App开发——职前通应用App开发(下)
华为·harmonyos
Rainman博1 天前
WMS-窗口relayout&FinishDrawing
android
摘星编程1 天前
React Native鸿蒙版:Image图片占位符
react native·react.js·harmonyos
baidu_247438611 天前
Android ViewModel定时任务
android·开发语言·javascript
大雷神1 天前
HarmonyOS智慧农业管理应用开发教程--高高种地-- 第30篇:设置与帮助系统
harmonyos
有位神秘人1 天前
Android中Notification的使用详解
android·java·javascript