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

相关推荐
铉铉这波能秀1 小时前
如何在Android Studio中使用Gemini进行AI Coding
android·java·人工智能·ai·kotlin·app·android studio
川石课堂软件测试2 小时前
什么是BUG,你对BUG的了解有多少?
android·linux·服务器·python·功能测试·bug·安全性测试
安卓开发者3 小时前
鸿蒙Next文件上传下载:全场景高效数据传输方案
华为·harmonyos
文火冰糖的硅基工坊5 小时前
[创业之路-687]:华为“1+8+N”战略以及其背后的技术栈、商业逻辑。
华为·重构·架构·创业
玩机达人885 小时前
三星S25Ultra/S24安卓16系统Oneui8成功获取完美root权限+LSP框架
android·linux·里氏替换原则
居安思危_Ho6 小时前
RK平台Uniapp自启动缓存问题解决
android·缓存·uni-app·rk平台·uniapp资源文件
molong9316 小时前
Activity/Service/Broadcast/ContentProvider 生命周期交互
android·学习·交互
molong9319 小时前
Android 权限模型(前台、后台、特殊权限)
android
怪兽20149 小时前
Looper、MessageQueue、Message及Handler的关系是什么?如何保证MessageQueue的并发访问安全?
android·面试