HarmonyOS实战开发-如何构建多种样式弹窗

news/2025/2/22 15:08:06

介绍

本篇Codelab将介绍如何使用弹窗功能,实现四种类型弹窗。分别是:警告弹窗、自定义弹窗、日期滑动选择器弹窗、文本滑动选择器弹窗。需要完成以下功能:

  1. 点击左上角返回按钮展示警告弹窗。
  2. 点击出生日期展示日期滑动选择器弹窗。
  3. 点击性别展示文本滑动选择器弹窗。
  4. 点击兴趣爱好(多选)展示自定义弹窗。

相关概念

  • 警告弹窗:显示警告弹窗组件,可设置文本内容与响应回调。
  • 自定义弹窗: 通过CustomDialogController类显示自定义弹窗。
  • 日期滑动选择器弹窗:根据指定范围的Date创建可以选择日期的滑动选择器,展示在弹窗上。
  • 文本滑动选择器弹窗:根据指定的选择范围创建文本选择器,展示在弹窗上。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

├──entry/src/main/ets             // 代码区 
│  ├──common
│  │  ├──constants
│  │  │  └──CommonConstants.ets   // 常量类
│  │  └──utils
│  │     ├──CommonUtils.ets       // 弹窗操作工具类
│  │     └──Logger.ets            // 日志打印工具类
│  ├──entryability
│  │  └──EntryAbility.ets         // 程序入口类
│  ├──pages
│  │  └──HomePage.ets             // 主页面
│  ├──view
│  │  ├──CustomDialogWidget.ets   // 自定义弹窗组件
│  │  ├──TextCommonWidget.ets     // 自定义Text组件
│  │  └──TextInputWidget.ets      // 自定义TextInput组件
│  └──viewmodel
│     └──HobbyModel.ets           // 兴趣爱好model类
└──entry/src/main/resources       // 资源文件目录

构建主页面

应用主页面采用Column容器嵌套自定义组件形式完成页面整体布局,效果如图所示:

从上面效果图可以看出,主界面由2个相同样式的文本输入框和3个相同样式的文本布局组成。我们可以将文本输入框抽取成TextInputWidget子组件。再将文本布局抽取成TextCommonWidget子组件。

  1. 在ets目录下,点击鼠标右键 > New > Directory,新建名为view的自定义子组件目录。然后在view目录下,点击鼠标右键 > New > ArkTS File,新建两个ArkTS文件,分别为TextInputWidget子组件、TextCommonWidget子组件。
  2. 文本输入框抽取成TextInputWidget子组件,效果如图所示:

// TextInputWidget.ets
@Component
export default struct TextInputWidget {
  // 文本框左侧图片
  private inputImage?: Resource; 
  // 文本框提示
  private hintText?: Resource;

  build() {
    Row() {
      Image(this.inputImage)
        ...
      TextInput({ placeholder: this.hintText })
        ...
    }
    ...
  }
}

3.文本布局抽取成TextCommonWidget子组件,效果如图所示:

// TextCommonWidget.ets
@Component
export default struct TextCommonWidget {
  // 显示内容
  @Link content: string;
  // 文字标题左侧图片
  private textImage?: Resource;
  // 文本标题
  private title?: Resource;
  // 点击事件回调
  onItemClick: () => void = () => {};

  build() {
    Row() {
      Image(this.textImage)
        ...
      Text(this.title)
        ...
      Text(this.content)
        ...
      Image($r('app.media.ic_arrow'))
        ....
    }
    .onClick(this.onItemClick)
    ...
  } 
}

4.在HomePage主界面引用TextInputWidget和TextCommonWidget子组件,然后初始化出生日期、性别、兴趣爱好默认数据。

// HomePage.ets
@Entry
@Component
struct HomePage {
  @State birthdate: string = '';
  @State sex: string = '';
  @State hobbies: string = '';

  build() {
    Column() {
      ...
      TextInputWeight({
        inputImage: $r("app.media.ic_nickname"),
        hintText: $r("app.string.text_input_hint")
      })
      TextCommonWeight({
        textImage: $r("app.media.ic_birthdate"),
        title: $r("app.string.title_birthdate"),
        content: $birthdate,
        onItemClick: () => {
          CommonUtils.datePickerDialog((birthValue: string) => {
            this.birthdate = birthValue;
          });
        }
      }) 
      TextCommonWeight({
        textImage: $r("app.media.ic_sex"),
        title: $r("app.string.title_sex"),
        content: $sex,
        onItemClick: () => {
          CommonUtils.textPickerDialog(this.sexArray, (sexValue: string) => {
            this.sex = sexValue;
          });
        }
      })
      TextInputWeight({
        inputImage: $r("app.media.ic_signature"),
        hintText: $r("app.string.text_input_signature")
      })
      TextCommonWeight({
        textImage: $r("app.media.ic_hobbies"),
        title: $r("app.string.title_hobbies"),
        content: $hobbies,
        onItemClick: () => {
          this.customDialogController.open();
        }
      })
    }
    ...
  }
}

警告弹窗

点击主页面左上角返回按钮,通过CommonUtils.alertDialog方法弹出警告弹窗,提醒用户是否进行当前操作,效果如图所示:

// CommonUtils.ets
alertDialog(context: Context.UIAbilityContext) {
  AlertDialog.show({
    // 提示信息
    message: $r('app.string.alert_dialog_message'), 
    // 弹窗显示位置
    alignment: DialogAlignment.Bottom,
    // 弹窗偏移位置
    offset: {
      dx: 0,
      dy: CommonConstants.DY_OFFSET
    },
    primaryButton: {
      ...
    },
    secondaryButton: {
      // 退出应用
      context.terminateSelf();
      ...
    }
  });
}

日期滑动选择器弹窗

点击出生日期选项,通过CommonUtils.datePickerDialog方法弹出日期选择器弹窗,根据需要选择相应时间,效果如图所示:

// CommonUtils.ets
datePickerDialog(dateCallback) {
  DatePickerDialog.show({
    // 开始时间
    start: new Date(CommonConstants.START_TIME),
    // 结束时间
    end: new Date(CommonConstants.END_TIME), 
    // 当前选中时间
    selected: new Date(),
    // 是否显示农历
    lunar: false,
    onAccept: (value: DatePickerResult) => {
      let year = value.year as number;
      let month = value.month as number + CommonConstants.PLUS_ONE;
      let day = value.day as number;
      let birthdate: string = this.getBirthDateValue(year, month, day);
      dateCallback(birthdate);
    }
  });
}

// 获取出生日期值
getBirthDateValue(year: number, month: number, day: number): string {
  let birthdate: string = `${year}${CommonConstants.DATE_YEAR}${month}` +
    `${CommonConstants.DATE_MONTH}${day}${CommonConstants.DATE_DAY}`;
  return birthdate;
}  

// HomePage.ets
build() {
  Column() {
    ...
    TextCommonWeight({
      textImage: $r('app.media.ic_birthdate'),
      title: $r("app.string.title_birthdate"),
      content: $birthdate,
      onItemClick: () => {
        CommonUtils.datePickerDialog((birthValue: string) => {
          this.birthdate = birthValue;
        });
      }
    })
    ...
  }
  ...
}

文本滑动选择器弹窗

点击性别选项,通过CommonUtils.textPickerDialog方法弹出性别选择器弹窗,根据需要选择相应性别,效果如图所示:

// CommonUtils.ets
textPickerDialog(sexArray: Resource, sexCallback: (sexValue: string) => void) {
  TextPickerDialog.show({
    range: sexArray,
    selected: 0,
    onAccept: (result: TextPickerResult) => {
      sexCallback(result.value);
    },
    onCancel: () => {
      ...
    }
  });
}

// HomePage.ets
build() {
  Column() {
    ...
    TextCommonWeight({
      textImage: $r('app.media.ic_sex'),
      title: $r("app.string.title_sex"),
      content: $sex,
      onItemClick: () => {
        CommonUtils.textPickerDialog(this.sexArray, (sexValue: string) => {
          this.sex= sexValue;
        });
      }
    })
    ...
  }
  ...
}

自定义弹窗

点击兴趣爱好选项,通过customDialogController.open方法弹出自定义弹窗,根据需要选择相应的兴趣爱好,效果如图所示:

自定义弹窗实现分为以下步骤:

  1. 在view目录下,点击鼠标右键 > New > ArkTS File,新建一个ArkTS文件,然后命名为CustomDialogWeight子组件。
  2. 在CustomDialogWeight的aboutToAppear方法,通过manager.getStringArrayValue方法获取本地资源数据进行初始化。
// CustomDialogWeight.ets
@State hobbyModels: HobbyModel[] = [];

aboutToAppear() {
  let context: Context = getContext(this);
  if (CommonUtils.isEmpty(context) || CommonUtils.isEmpty(context.resourceManager)) {
    Logger.error(CommonConstants.TAG_CUSTOM, 'context or resourceManager is null');
    return;
  }
  let manager = context.resourceManager;
  manager.getStringArrayValue($r("app.strarray.hobbies_data").id, (error, hobbyArray) => {
    if (!CommonUtils.isEmpty(error)) {
      Logger.error(CommonConstants.TAG_CUSTOM, 'error = ' + JSON.stringify(error));
    } else {
      hobbyArray.forEach((hobbyItem: string) => {
        let hobbyModel = new HobbyModel();
        hobbyModel.label = hobbyItem;
        hobbyModel.isChecked = false;
        this.hobbyModels.push(hobbyModel);
      });
    }
  });
}

3.当用户点击确定按钮时,通过setHobbiesValue方法处理自定义弹窗选项结果。

// CustomDialogWeight.ets
@State hobbyModels: HobbyModel[] = [];
@Link hobbies: string;

// 处理自定义弹窗选项结果
setHobbiesValue(hobbyModels: HobbyModel[]) {
  if (CommonUtils.isEmptyArr(hobbyModels)) {
    Logger.error(CommonConstants.TAG_CUSTOM, 'hobbyModels length is 0');
    return;
  }
  let hobbiesText: string = '';
  hobbiesText = hobbyModels.filter((isCheckItem: HobbyModel) => isCheckItem?.isChecked)
    .map((checkedItem: HobbyModel) => {
      return checkedItem.label;
    })
    .join(CommonConstants.COMMA);
  if (hobbiesText.length > 0) {
    this.hobbies = hobbiesText;
  }
}

build() {
  Column() {
    ...
    Row() {
      Button($r('app.string.cancel_button'))
        .dialogButtonStyle()
        .onClick(() => {
          this.controller.close();
        })
      Blank()
        ...
      Button($r('app.string.definite_button'))
        .dialogButtonStyle()
        .onClick(() => {
          this.setHobbiesValue(this.hobbyModels);
          this.controller.close();
        })
    }
  }
  ...
}

@Extend(Button) function dialogButtonStyle() {
  ....
}

4.通过@Link修饰的hobbies把值赋给HomePage的hobbies,然后hobbies刷新显示内容。

// HomePage.ets
@State hobbies: string = '';
customDialogController: CustomDialogController = new CustomDialogController({
  builder: CustomDialogComponent({
    hobbies: $hobbies
  }),
  alignment: DialogAlignment.Bottom,
  customStyle: true,
  offset: {
    dx: 0,
    dy: CommonConstants.DY_OFFSET
  }
});

build() {
  Column() {
    ...
    TextCommonWeight({
      textImage: $r('app.media.ic_hobbies'),
      title: $r("app.string.title_hobbies"),
      content: $hobbies,
      onItemClick: () => {
        // 打开自定义弹窗
        this.customDialogController.open();
      }
    })
  }
  ...
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 使用CustomDialogController实现自定义弹窗。
  2. 使用AlertDialog实现警告弹窗。
  3. 使用DatePickerDialog实现日期滑动选择弹窗。
  4. 使用TextPickerDialog实现文本滑动选择弹窗。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→《HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等.....视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→鸿蒙生态应用开发白皮书V2.0PDF》

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

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

二、HarmonyOS 概念

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

三、如何快速入门?《做鸿蒙应用开发>鸿蒙应用开发到底学习些啥?》

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

四、开发基础知识

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

五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

更多了解更多鸿蒙开发的相关知识可以参考:鸿蒙 (Harmony OS)开发学习手册》


http://www.niftyadmin.cn/n/5459781.html

相关文章

taskkill /f /fi “windowtitle eq 窗口标题“ /t 踩坑

最近在window11 上部署一个自动化脚本,目的:通过定时任务定时重启某个java任务 脚本 push-to-start.bat echo offtaskkill /f /fi "WINDOWTITLE eq xxx" /tstart cmd /k "cd/d D:\qt\projects && start-node.bat"脚本start-…

Java的Prim算法知识点(含面试大厂题和源码)

Prim算法是一种用于求解加权无向图的最小生成树问题的贪心算法。最小生成树是指在一个加权无向图中,连接所有顶点的权值最小的树。Prim算法通过逐步增加新的边和顶点来构建最小生成树。以下是Prim算法的一些关键知识点: 1. 算法概述 Prim算法从图中的任…

shell命令运行原理

shell命令运行原理 Linux严格意义上说的是一个操作系统,我们称之为“核心(kernel)”,但我们一般用户,不能直接使用kernel。 而是通过kernel的“外壳”程序,也就是所谓的shell,来与kernel沟通。…

基于 StarRocks 的风控实时特征探索和实践

背景 金融风控特征是在金融领域中用于评估和管理风险的关键指标。它们帮助金融机构识别潜在风险,降低损失,并采取措施规避风险。例如,用户最后一次授信提交时间就是一个重要的金融风控特征。 金融风控实时特征场景是一个典型的大数据实时业务…

【R语言从0到精通】-2-数据结构

通过上次的教程,我们已经安装好了R语言,且认识了基本的界面及操作,那么我们直接进入下一个问题,数据结构。 【R语言从0到精通】-1-下载R语言与R最基础内容-CSDN博客 2.1 数据结构概述 数据结构是一种组织和存储数据的方式&#…

平价的挂耳式耳机有哪些?五大高口碑品牌,深度测评严选!

随着技术的发展,市面上的一些高端开放式耳机已经在音质上有了显著的提升,甚至可以媲美一些入耳式耳机。与传统入耳式耳机相比,开放式耳机不会对耳道造成压迫,这减少了耳朵的疲劳感,使得长时间聆听音乐变得更加舒适。由…

【企业动态】成都九号诶艾科技有限公司基本信息

成都九号诶艾科技有限公司基本情况概述 公司基本信息 成都九号诶艾科技有限公司成立于2023年7月4日,位于中国(四川)自由贸易试验区成都高新区。该公司主要从事人工智能应用软件开发、人工智能基础软件开发以及互联网数据服务等相关业务。此外,九号诶艾科技还涉足旅游开发项…

YOLOv9改进策略 :block优化 | 无需TokenMixer也能达成SOTA性能的极简ViT架构 | CVPR2023 RIFormer

💡💡💡本文改进内容: token mixer被验证能够大幅度提升性能,但典型的token mixer为自注意力机制,推理耗时长,计算代价大,而RIFormers是无需TokenMixer也能达成SOTA性能的极简ViT架构…