HarmonyOS NEXT - picker 选择器( 包含 单列、多列、底部选择器)

server/2025/2/19 9:18:39/

demo 地址: https://github.com/iotjin/JhHarmonyDemo
组件对应代码实现地址
代码不定时更新,请前往github查看最新代码

在demo中这些组件和工具类都通过module实现了,具体可以参考HarmonyOS NEXT - 通过 module 模块化引用公共组件和utils

HarmonyOS NEXT - picker 选择器(包含 单列、多列、底部选择器)

  • 效果图
  • 调用方式
  • JhPickerTool.ets 完整代码

官方dialog 比较反人类,调用比较麻烦,下面两种还略微好点

  • 通过promptAction.openCustomDialog 实现自定义弹窗。对应官方文档
  • 不依赖UI组件的全局自定义弹出框 (openCustomDialog)(推荐)对应官方文档

在三方库上找了一个弹框库,简单调整样式封装了一层

三方库地址:
@pura/harmony-dialog(V1.0.7)

需要先在项目中导入三方库

 ohpm i @pura/harmony-dialog@1.0.7

OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包

!!!注意: 这个组件和JhDialog.ets 使用的同一配置,初始化使用Jhdialog 的初始化就可以了

下面是Jhdialog 使用的文章地址:
HarmonyOS NEXT - Dialog 和完全自定义弹框

效果图

在这里插入图片描述在这里插入图片描述-
在这里插入图片描述在这里插入图片描述在这里插入图片描述

调用方式

需要先全局初始化一次,否则弹框不显示
全局初始化可以放在入口的page处
1.0.8开始需要在在windowStage.loadContent 后执行初始化

以下是在第一个page的aboutToAppear方法初始化的

  aboutToAppear() {// 初始化Loadinglet uiContext: UIContext = this.getUIContext();JhDialog.initConfig(uiContext)}
  • BottomSheet-不带标题
   JhPickerTool.showBottomSheet({data: ['hello', 'world', '123'],clickCallback: (index, text) => {console.error('index', index)console.error('text', text)JhProgressHUD.showToast(text)}})
  • BottomSheet-带标题
   JhPickerTool.showBottomSheet({title: '请选择',data: ['hello', 'world', '123'],clickCallback: (index, text) => {console.error('index', index)console.error('text', text)JhProgressHUD.showToast(text)}})
  • BottomSheet-红色按钮
  JhPickerTool.showBottomSheet({title: '请选择操作',data: [{value: "保存本地",fontSize: 18}, {value: "删除",fontColor: Color.Red,fontSize: 18}],clickCallback: (index, text) => {console.error('index', index)console.error('text', text)JhProgressHUD.showToast(text)}})
  • JhPickerTool-单列(字符串数组)
	  const stringArr = ['11', '22', '33', '44']JhPickerTool.showStringPicker({data: stringArr,title: '请选择类型',selectIndex: 1,onCancel: () => {console.error(`点击了取消按钮`)},onConfirm: (selectValue, selectIndex: Number) => {console.error(`点击了确认按钮`)console.error('selectValue:', selectValue)console.error('selectIndex:', selectIndex)JhProgressHUD.showToast(selectValue.toString())},})
  • JhPickerTool-单列(对象数组)
	const dictArr: ItemType[] = [{ 'label': '类型一', 'value': '1' },{ 'label': '类型二', 'value': '2' },{ 'label': '类型三', 'value': '3' },]JhPickerTool.showStringPicker({data: dictArr,title: '请选择',labelKey: 'label',selectIndex: 2,onCancel: () => {console.error(`点击了取消按钮`)},onConfirm: (selectValue, selectIndex: Number) => {console.error(`点击了确认按钮`)console.error('selectValue:', JSON.stringify(selectValue))console.error('selectValue-label:', selectValue['label'])console.error('selectIndex:', selectIndex)JhProgressHUD.showToast(JSON.stringify(selectValue))},})
  • JhPickerTool-两列(对象数组)
		const dictArr2: ItemType[][] = [[{ 'label': '大类一', 'value': '1' },{ 'label': '大类二', 'value': '2' },{ 'label': '大类三', 'value': '3' },],[{ 'label': '小类一', 'value': '11' },{ 'label': '小类二', 'value': '22' },],]JhPickerTool.showArrayPicker({data: dictArr2,title: '请选择',selectIndex: [1, 1],labelKey: 'label',onCancel: () => {console.error(`点击了取消按钮`)},onConfirm: (selectItemArr, selectIndexArr: Number[]) => {console.error(`点击了确认按钮`)console.error('selectItemArr:', JSON.stringify(selectItemArr))console.error('selectIndexArr:', JSON.stringify(selectIndexArr))JhProgressHUD.showToast(JSON.stringify(selectItemArr))},})
  • JhPickerTool-三列(对象数组)
	const dictArr3: ItemType[][] = [[{ 'label': '大类一', 'value': '1' },{ 'label': '大类二', 'value': '2' },{ 'label': '大类三', 'value': '3' },],[{ 'label': '中类一', 'value': '1' },{ 'label': '中型二', 'value': '2' },{ 'label': '中型三', 'value': '3' },{ 'label': '中型四', 'value': '4' },],[{ 'label': '小类一', 'value': '1' },{ 'label': '小类二', 'value': '2' },],]JhPickerTool.showArrayPicker({data: dictArr3,title: '请选择',selectIndex: [1, 2, 1],labelKey: 'label',onCancel: () => {console.error(`点击了取消按钮`)},onConfirm: (selectItemArr, selectIndexArr: Number[]) => {console.error(`点击了确认按钮`)console.error('selectItemArr:', JSON.stringify(selectItemArr))console.error('selectIndexArr:', JSON.stringify(selectIndexArr))JhProgressHUD.showToast(JSON.stringify(selectItemArr))},})

JhPickerTool.ets 完整代码

///  JhPickerTool.ets
///
///  Created by iotjin on 2024/12/25. 
///  description:  @pura/harmony-dialog 封装。JhDialog、JhToast、JhPickerTool共用同一默认配置import { SheetOptions, DialogAction, DialogHelper, OnActionCallBack } from "@pura/harmony-dialog"
import { KColors } from "../configs/Colors"const _labelKey = 'label' // 对象数组的文字字段
const _titleText = '请选择'
const _cancelText = '取消'
const _confirmText = '确认'const _kTitleFontSize = 18.0
const _kBtnFontSize = 17.0
const _textFontSize = 18.0
const _selectTextFontSize = 20.0
const _kHeaderRadius = 10.0const _bgColor = KColors.kPickerBgColor
const _titleColor = KColors.kPickerTitleColor
const _btnColor = KColors.kPickerBtnColor
// const  _headerColor = '#E6E6E6'
const _headerColor = KColors.kPickerHeaderColor
const _selectTextColor = KColors.kPickerTextColor
const _otherTextColor = KColors.kLightGreyTextColorexport interface JhPickerOptions {data?: ESObject[] // 数据源labelKey?: string, // 对象数组的文字字段, 默认_labelKeyselectIndex?: number | number[]title?: ResourceStrleftText?: ResourceStrrightText?: ResourceStronCancel?: () => void/// 选择回调/// 单列选择器返回选中行对象和index/// 多列选择器返回选中行对象数组和index数组onConfirm?: (selectValue: string | string[], selectIndexArr: ESObject) => void
}export interface JhBottomSheetOptions {data?: Array<SheetOptions> | Array<ResourceStr>; // 数据源title?: ResourceStr/// 选择回调/// index 从上往下 0,1,2clickCallback?: (selectIndex: number, selectText: string) => void
}export class JhPickerTool {/*** 底部弹框* @param options*/public static showBottomSheet(options: JhBottomSheetOptions) {if ((options.data ?? []).length == 0) {return}DialogHelper.showBottomSheetDialog({title: options.title ?? '',titleFontColor: _titleColor,cancelValue: _cancelText,sheets: options.data ?? [],cornerRadius: _kHeaderRadius,backgroundColor: _bgColor,autoCancel: true, // 点击遮障层时,是否关闭弹窗,true表示关闭弹窗。默认关闭backCancel: false, // 点击返回键或手势返回时,是否关闭弹窗;实现onWillDismiss函数时,该参数不起作用。默认不关闭actionCancel: true, // 点击操作按钮时,是否关闭弹窗。false表示不关闭弹窗。onAction: (index) => {const isStringArray = JhPickerTool.isOneStringArray(options.data)const selectedText: string = isStringArray ? options.data![index] : options.data![index]['value']options.clickCallback?.(index, selectedText)}})}/*** 单列选择器* 单列选择器返回选中行对象和index* @param options*/public static showStringPicker(options: JhPickerOptions) {const originalList: ESObject[] = options.data ?? []if (originalList.length == 0 || !JhPickerTool.isOneDimensionalArray(originalList)) {return}const isStringArray = JhPickerTool.isOneStringArray(originalList)const labelKey = options.labelKey ?? _labelKeyconst tempList: string[] = originalList.map((item: ESObject) => {return (isStringArray ? item : item[labelKey]) as string})DialogHelper.showTextPickerDialog({range: tempList,value: tempList[options.selectIndex as number ?? 0],title: options.title ?? _titleText,titleFontColor: _titleColor,titleBackground: _headerColor,primaryButton: {value: options.leftText ?? _cancelText,fontColor: _btnColor,},secondaryButton: {value: options.rightText ?? _confirmText,fontColor: _btnColor,},//设置所有选项中最上和最下两个选项的文本颜色、字号、字体粗细。disappearTextStyle: { color: _otherTextColor, font: { size: _textFontSize } },//设置所有选项中除了最上、最下及选中项以外的文本颜色、字号、字体粗细。textStyle: { color: _otherTextColor, font: { size: _textFontSize } },//设置选中项的文本颜色、字号、字体粗细。selectedTextStyle: { color: _selectTextColor, font: { size: _selectTextFontSize } },cornerRadius: _kHeaderRadius,backgroundColor: _bgColor,canLoop: false,autoCancel: true, // 点击遮障层时,是否关闭弹窗,true表示关闭弹窗。默认关闭backCancel: false, // 点击返回键或手势返回时,是否关闭弹窗;实现onWillDismiss函数时,该参数不起作用。默认不关闭actionCancel: true, // 点击操作按钮时,是否关闭弹窗。false表示不关闭弹窗。onChange: (value: string | string[], index: number | number[]): void => {// console.log(`value: ${value}`)// console.log(`index: ${index}`)},onAction: (action: number, dialogId: string, value: string | string[]) => {if (action == DialogAction.ONE) {options.onCancel?.()} else {if (isStringArray) {const foundIndex = tempList.findIndex((item) => item === value)const selectIndex = foundIndex === -1 ? 0 : foundIndexoptions.onConfirm?.(value, selectIndex)} else {const foundIndex = originalList.findIndex((item: ESObject) => item[labelKey] === value)const selectIndex = foundIndex === -1 ? 0 : foundIndexoptions.onConfirm?.(originalList[selectIndex], selectIndex)}}}})}/*** 多列选择器* 多列选择器返回选中行对象数组和index数组* @param options*/public static showArrayPicker(options: JhPickerOptions) {const originalList: ESObject[] = options.data ?? []if (originalList.length == 0 || JhPickerTool.isOneDimensionalArray(originalList)) {return}const isMultiStringArray = JhPickerTool.isMultiStringArray(originalList)const labelKey = options.labelKey ?? _labelKeylet tempList: string[][] = originalListif (!isMultiStringArray) {const labelArr: string[][] = originalList.map((subArray: ESObject) => {return subArray.map((item: ESObject) => item[labelKey] as string) as string[]})tempList = labelArr}let valueList: string[] = []if (options.selectIndex && Array.isArray(options.selectIndex)) {for (let i = 0; i < options.selectIndex!.length; i++) {let columnData: ESObject = originalList[i]const index = options.selectIndex![i]if (index >= 0 && index < columnData.length) {valueList.push(isMultiStringArray ? columnData[index] : columnData[index][labelKey])} else {valueList.push(isMultiStringArray ? columnData[0] : columnData[0][labelKey])}}}DialogHelper.showTextPickerDialog({range: tempList,value: valueList,title: options.title ?? _titleText,titleFontColor: _titleColor,titleBackground: _headerColor,primaryButton: {value: options.leftText ?? _cancelText,fontColor: _btnColor,},secondaryButton: {value: options.rightText ?? _confirmText,fontColor: _btnColor,},//设置所有选项中最上和最下两个选项的文本颜色、字号、字体粗细。disappearTextStyle: { color: _otherTextColor, font: { size: _textFontSize } },//设置所有选项中除了最上、最下及选中项以外的文本颜色、字号、字体粗细。textStyle: { color: _otherTextColor, font: { size: _textFontSize } },//设置选中项的文本颜色、字号、字体粗细。selectedTextStyle: { color: _selectTextColor, font: { size: _selectTextFontSize } },cornerRadius: _kHeaderRadius,backgroundColor: _bgColor,canLoop: false,autoCancel: true, // 点击遮障层时,是否关闭弹窗,true表示关闭弹窗。默认关闭backCancel: false, // 点击返回键或手势返回时,是否关闭弹窗;实现onWillDismiss函数时,该参数不起作用。默认不关闭actionCancel: true, // 点击操作按钮时,是否关闭弹窗。false表示不关闭弹窗。onChange: (value: string | string[], index: number | number[]): void => {// console.log(`value: ${value}`)// console.log(`index: ${index}`)},onAction: (action: number, dialogId: string, values: string | string[]) => {if (action == DialogAction.ONE) {options.onCancel?.()} else {if (Array.isArray(values)) {let selectItemArr: ESObject = []let selectIndexArr: number[] = []for (let i = 0; i < values.length; i++) {let columnData: ESObject = originalList[i]const value = values[i]const foundIndex: number = columnData.findIndex((item: ESObject) => (isMultiStringArray ? item : item[labelKey]) === value)const selectIndex = foundIndex === -1 ? 0 : foundIndexselectIndexArr.push(selectIndex)selectItemArr.push(columnData[selectIndex])}options.onConfirm?.(selectItemArr, selectIndexArr)}}}})}/*** 是否是一维数组* @param arr* @returns*/public static isOneDimensionalArray(arr: ESObject[]) {// 检查是否为数组,并且数组内元素不是数组, 使用 some 方法检查是否有任何元素是数组,如果存在,则说明是非一维数组return Array.isArray(arr) && !arr.some((item: ESObject) => Array.isArray(item))}/*** 是否是一维字符串数组* @param arr* @returns*/public static isOneStringArray(arr: ESObject[]) {return Array.isArray(arr) && arr.every((item: ESObject) => typeof item === 'string')}/*** 是否是多维字符串数组* @param arr* @returns*/public static isMultiStringArray(arr: ESObject[]) {// 如果不是数组,直接返回 falseif (!Array.isArray(arr)) {return false}// 检查数组中的每个元素是否是字符串数组return arr.every((item: ESObject): boolean => JhPickerTool.isOneStringArray(item))}
}

http://www.ppmy.cn/server/167561.html

相关文章

STM32简介

一、ST主要产品 STM32命名规则

【办公】钉钉修改默认存储位置,释放C盘空间

Step1: 右击钉钉图标选择设置 Step2: 通用里面找到文件保存位置&#xff0c;修改文件目录: 最新版本钉钉界面&#xff1a; 设置完成后按提示重启即可&#xff01;

Unity UI 道路线跟随:让图标沿道路轨迹移动

在 Unity UI 开发中&#xff0c;有时需要让图标沿着一条道路轨迹移动&#xff0c;比如地图上的车辆行驶动画、导航路径指示等。本文介绍如何基于 UI 图片中的道路线生成曲线&#xff0c;并使用 Slider 控制图标沿轨迹运动&#xff0c;适用于 UI 导航、路径跟随动画等场景。 1. …

消息中间件:RabbitMQ镜像集群部署配置全流程

目录 1、特点 2、RabbitMQ的消息传递模式 2.1、简单模式&#xff08;Simple Mode&#xff09; 2.2、工作队列模式&#xff08;Work Queue Mode&#xff09; 2.3、发布/订阅模式&#xff08;Publish/Subscribe Mode&#xff09; 2.4、路由模式&#xff08;Routing Mode&am…

Shell 概述

shell简介 echo $SHELL/bin/bash 创建第一个shell脚本 touch helloworld.sh vim helloworld.sh在helloworld.sh 中输入如下内容&#xff1a; #!/bin/bash echo “helloworld” 执行shell文件 bash/sh 文件的相对路径或者绝对路径 bash hellowrold.sh hello,world sh /ro…

【Python】如何在 Linux/Windows 系统中设置 PYTHONPATH 环境变量

什么是 PYTHONPATH&#xff1f; PYTHONPATH 是一个环境变量&#xff0c;它告诉 Python 解释器在哪些目录中查找要导入的模块。这对于包含不在标准目录中的自定义模块非常有用。 Linux 系统中设置 PYTHONPATH 环境变量 在 Python 开发环境中&#xff0c;正确设置 PYTHONPATH …

【JavaScript】异步编程汇总

异步编程解决方案&#xff1a; 回调函数PromiseGeneratorawait / async 回调函数 回调函数是早期处理异步编程的主要方式&#xff0c;虽然它本身存在很多的缺陷&#xff0c;比如那个时候对于复杂的异步处理常常会出现回调地狱。 但是因为 JavaScript 中当时并没有很好的API来帮…

2025年智慧城市解决方案下载:AI-超脑中台,体系架构整体设计

2025年&#xff0c;随着人工智能、物联网、大数据等新兴技术的深度融合&#xff0c;智慧城市解决方案正迈向更高层次的智能化和协同化阶段。其中&#xff0c;AI-超脑中台作为核心架构的一部分&#xff0c;为城市智能化运行提供了强大支撑。 智慧城市最新解决方案&#xff0c;标…