在移动应用中地址选择是一项高频且有一定复杂度的交互。从省到市再到区三层级联关系需要选择器具备上级联动下级的能力。HarmonyOS NEXT ArkUI 的 TextPicker 组件就是为这类场景而生的——它不仅支持单列文本选择更支持多列模式和级联数据天然适配地址选择、分类筛选等层级化选择场景。本文将从 TextPicker 的基础 API 出发深入讲解级联模式的原理与实现并构建一个完整的地址选择器——包含省市区的三层级联、快捷城市预设和层级切换功能。关键词HarmonyOS、ArkUI、TextPicker、级联选择、地址选择器、联动一、TextPicker 组件概览TextPicker 是 ArkUI 的通用文本选择器组件采用滚轮交互模式支持三种数据结构模式range 类型列数典型场景单列string[]1性别、血型、星座多列string[][]2身高米厘米、车牌省编号级联TextCascadePickerRangeContent[]2地址、行业分类、组织架构其中级联模式是 TextPicker 最强大的特性。它通过TextCascadePickerRangeContent定义层级化的树形数据当用户在上一级做出选择后下一级的选项会自动更新为对应子节点。这种联动行为由组件内部自动处理开发者只需提供正确的数据结构。二、核心 API2.1 构造函数TextPicker({range:string[]|string[][]|TextCascadePickerRangeContent[],selected:number|number[],value:string|string[]})参数说明range数据源。可以是简单的字符串数组、二维数组或级联结构selected初始选中项的索引数组每个元素对应该列的选中位置value初始选中项的文本数组与selected对应2.2 TextCascadePickerRangeContent 接口这是级联模式的核心数据类型interfaceTextCascadePickerRangeContent{text:string|Resource;// 当前节点的显示文本children?:TextCascadePickerRangeContent[];// 子节点列表}这个接口非常简单——每个节点有text显示文本和可选的children子节点。顶层数组是第一级选项如省份每个选项的children是第二级选项如城市以此类推。2.3 onChange 回调当用户滑动滚轮改变选择时触发.onChange((value:string|string[],index:number|number[]){// value: 当前选中的文本值级联模式下为 string[]// index: 当前选中的索引位置级联模式下为 number[]})在级联模式下value和index都是数组类型长度等于当前列数。2.4 关键属性属性类型说明.defaultPickerItemHeightnumber | string每列选项的高度.canLoopboolean是否循环滚动默认true.disappearTextStylePickerTextStyle非选中项的文字样式.selectedTextStylePickerTextStyle选中项的文字样式三、实战地址选择器我们来实现一个完整的地址选择器——支持省/市/区三级级联、6 个快捷城市预设和层级切换在 2 级和 3 级之间切换。3.1 数据准备首先定义级联数据结构。我们使用 5 个省级区域每个省下有 3-4 个城市每个城市下有 3-4 个区/街道privatefullData:RegionNode[][{text:北京市,children:[{text:东城区,children:[{text:东华门街道},{text:景山街道},{text:安定门街道}]},{text:西城区,children:[{text:西长安街街道},{text:金融街街道},{text:什刹海街道}]},{text:朝阳区,children:[{text:望京街道},{text:三里屯街道},{text:国贸}]},{text:海淀区,children:[{text:中关村街道},{text:五道口街道},{text:上地街道}]}]},// ... 上海市、广东省、浙江省、四川省];这是标准的TextCascadePickerRangeContent[]格式——顶层是省份children是城市城市的children是区/街道。3.2 动态构建 2 级数据为了支持层级切换我们在aboutToAppear中动态构建一份不含区/街道的 2 级数据aboutToAppear():void{this.twoLevelData[];for(leti0;ithis.fullData.length;i){constprovthis.fullData[i];constcityList:RegionNode[][];if(prov.children){for(letj0;jprov.children.length;j){cityList.push({text:prov.children[j].text});// 不包含 children}}this.twoLevelData.push({text:prov.text,children:cityList});}this.updateAddress();}通过遍历原始数据并剥离城市节点下的children我们得到一份干净的 2 级级联结构。Toggle 开关切换时直接切换range的数据源即可。3.3 TextPicker 集成将数据接入 TextPicker根据showDistrict状态动态选择 2 级或 3 级数据TextPicker({range:this.showDistrict?this.fullData:this.twoLevelData,selected:this.showDistrict?this.selectedIdx:[this.selectedIdx[0],this.selectedIdx[1]],value:this.selectedVal}).onChange((value:string|string[],index:number|number[]){this.onPickerChange(value,index);})关键设计点2 级模式的selected数组长度是 2省、市3 级模式长度是 3省、市、区。切换模式时需要同步调整selected和value的数组长度。3.4 选择结果展示地址选择的结果展示在一个信息卡片中——显示当前选中的完整地址和对应的索引路径Column(){Row(){Text().fontSize(22).margin({right:10})Text(this.addressText).fontSize(18).fontColor(#1a1a2e).fontWeight(FontWeight.Bold)}Row(){Text(层级).fontSize(11).fontColor(#9999AA)Text(this.selectedIdx.join( → )).fontSize(11).fontColor(#9999AA)}.margin({top:8})}.width(100%).padding({left:Spacing.LG,right:Spacing.LG,top:14,bottom:14}).backgroundColor(#F0F6FF)卡片使用浅蓝底色#F0F6FF与页面其他区域区分地址文本使用大号加粗字体凸显选择结果索引路径作为辅助信息以灰色小字展示。3.5 快捷预设提供 6 个常用城市/区组合的快捷入口让用户一键跳转到常见地址Row(){this.PresetBtn(北京 · 朝阳,(){this.applyPreset(0,2,0);})this.PresetBtn(北京 · 海淀,(){this.applyPreset(0,3,0);})this.PresetBtn(上海 · 浦东,(){this.applyPreset(1,0,0);})}点击任意预设按钮调用applyPreset方法同时更新selectedIdx和selectedValapplyPreset(pIdx:number,cIdx:number,dIdx:number):void{this.selectedIdx[pIdx,cIdx,dIdx];constprovthis.fullData[pIdx].text;constcitythis.fullData[pIdx].children![cIdx].text;constdistthis.fullData[pIdx].children![cIdx].children![dIdx].text;this.selectedVal[prov,city,dist];this.updateAddress();}注意预设按钮使用Builder方法提取为可复用组件BuilderPresetBtn(label:string,onClick:()void){Text(label).fontSize(12).fontColor(#1677FF).fontWeight(FontWeight.Medium).padding({top:8,bottom:8,left:12,right:12}).borderRadius(8).backgroundColor(#EEF3FF).margin({right:8}).onClick(onClick)}3.6 层级切换使用 Toggle 开关在 2 级和 3 级之间动态切换Toggle({type:ToggleType.Switch,isOn:this.showDistrict}).onChange((on:boolean){this.showDistricton;this.selectedIdx[0,0,0];if(on){this.selectedVal[北京市,东城区,东华门街道];}else{this.selectedVal[北京市,东城区];}this.updateAddress();})切换时重置选中位置到第一项并根据新模式设置对应长度的 value 数组。四、级联原理与自定义联动TextPicker 的级联行为是自动的——当用户在第一列选择了一个新省份组件内部会查找该省份的children并更新第二列选项。但这仅限于组件内部。如果需要额外的自定义联动逻辑如在选择结果卡中实时更新、触发搜索等你需要在onChange回调中处理onPickerChange(value:string|string[],index:number|number[]):void{if(Array.isArray(value)){this.selectedValvalueasstring[];}if(Array.isArray(index)){this.selectedIdxindexasnumber[];}this.updateAddress();// 自定义逻辑更新结果展示}这里的类型判断Array.isArray(value)是因为onChange的参数类型是联合类型string | string[]。在级联模式下参数始终是数组类型即使只有 2 级时也是 2 元数组。五、完整交互流程初始状态显示 3 级级联选择器默认选中北京市 - 东城区 - 东华门街道结果卡片展示完整地址手动选择滑动第一列切换省份例如从北京市到广东省第二列自动变为广东省下的城市列表广州市、深圳市、东莞市、佛山市第三列相应更新切换层级关闭显示街道/镇开关选择器变为 2 级省 - 市第三列消失快捷预设点击深圳 · 南山按钮选择器自动跳转到广东省 - 深圳市 - 南山区打开层级重新打开开关回到 3 级模式继续精确到街道/镇级别六、注意事项6.1 数据完整性级联数据必须是完整的树形结构——每个节点的children要么全部存在要么全部不存在。不完整的结构如部分城市有区、部分没有可能导致级联行为异常。6.2 索引范围在 2 级和 3 级之间切换时selected索引数组的长度必须与级数匹配。3 级时需要 3 个索引2 级时需要 2 个。长度不匹配会导致运行时错误。6.3 数据规模TextPicker 会在内存中持有完整的级联数据。对于地址选择这类数据量适中的场景数百个省市、数千个区性能没有问题。但如果数据量极大如数十万条建议考虑异步加载方案。6.4 与 DatePicker 的区别TextPicker 和 DatePicker 虽然外观相似都是滚轮选择但用途完全不同DatePicker 专用于日期选择列固定为年/月/日数据由系统生成TextPicker 是通用选择器列数和数据完全由开发者定义七、总结TextPicker 是 ArkUI 中最灵活的选择器组件。从简单的单列选择性别、血型到复杂的多级级联地址、行业它都能胜任。其核心优势在于三种模式覆盖所有场景单列简单、多列独立、级联联动级联行为自动处理开发者只需提供树形数据无需手动实现联动逻辑灵活的显示控制通过 CSS 属性控制样式适应不同设计需求本文通过地址选择器这个完整的实战案例覆盖了 TextPicker 级联模式的核心用法——从数据构建到选择器集成、从结果展示到快捷预设、从层级切换到联动逻辑。掌握了这些技术你就能在任何需要层级化选择的场景中游刃有余。
鸿蒙新特性:TextPicker 级联选择器详解——构建智能地址选择器
发布时间:2026/7/6 4:39:16
在移动应用中地址选择是一项高频且有一定复杂度的交互。从省到市再到区三层级联关系需要选择器具备上级联动下级的能力。HarmonyOS NEXT ArkUI 的 TextPicker 组件就是为这类场景而生的——它不仅支持单列文本选择更支持多列模式和级联数据天然适配地址选择、分类筛选等层级化选择场景。本文将从 TextPicker 的基础 API 出发深入讲解级联模式的原理与实现并构建一个完整的地址选择器——包含省市区的三层级联、快捷城市预设和层级切换功能。关键词HarmonyOS、ArkUI、TextPicker、级联选择、地址选择器、联动一、TextPicker 组件概览TextPicker 是 ArkUI 的通用文本选择器组件采用滚轮交互模式支持三种数据结构模式range 类型列数典型场景单列string[]1性别、血型、星座多列string[][]2身高米厘米、车牌省编号级联TextCascadePickerRangeContent[]2地址、行业分类、组织架构其中级联模式是 TextPicker 最强大的特性。它通过TextCascadePickerRangeContent定义层级化的树形数据当用户在上一级做出选择后下一级的选项会自动更新为对应子节点。这种联动行为由组件内部自动处理开发者只需提供正确的数据结构。二、核心 API2.1 构造函数TextPicker({range:string[]|string[][]|TextCascadePickerRangeContent[],selected:number|number[],value:string|string[]})参数说明range数据源。可以是简单的字符串数组、二维数组或级联结构selected初始选中项的索引数组每个元素对应该列的选中位置value初始选中项的文本数组与selected对应2.2 TextCascadePickerRangeContent 接口这是级联模式的核心数据类型interfaceTextCascadePickerRangeContent{text:string|Resource;// 当前节点的显示文本children?:TextCascadePickerRangeContent[];// 子节点列表}这个接口非常简单——每个节点有text显示文本和可选的children子节点。顶层数组是第一级选项如省份每个选项的children是第二级选项如城市以此类推。2.3 onChange 回调当用户滑动滚轮改变选择时触发.onChange((value:string|string[],index:number|number[]){// value: 当前选中的文本值级联模式下为 string[]// index: 当前选中的索引位置级联模式下为 number[]})在级联模式下value和index都是数组类型长度等于当前列数。2.4 关键属性属性类型说明.defaultPickerItemHeightnumber | string每列选项的高度.canLoopboolean是否循环滚动默认true.disappearTextStylePickerTextStyle非选中项的文字样式.selectedTextStylePickerTextStyle选中项的文字样式三、实战地址选择器我们来实现一个完整的地址选择器——支持省/市/区三级级联、6 个快捷城市预设和层级切换在 2 级和 3 级之间切换。3.1 数据准备首先定义级联数据结构。我们使用 5 个省级区域每个省下有 3-4 个城市每个城市下有 3-4 个区/街道privatefullData:RegionNode[][{text:北京市,children:[{text:东城区,children:[{text:东华门街道},{text:景山街道},{text:安定门街道}]},{text:西城区,children:[{text:西长安街街道},{text:金融街街道},{text:什刹海街道}]},{text:朝阳区,children:[{text:望京街道},{text:三里屯街道},{text:国贸}]},{text:海淀区,children:[{text:中关村街道},{text:五道口街道},{text:上地街道}]}]},// ... 上海市、广东省、浙江省、四川省];这是标准的TextCascadePickerRangeContent[]格式——顶层是省份children是城市城市的children是区/街道。3.2 动态构建 2 级数据为了支持层级切换我们在aboutToAppear中动态构建一份不含区/街道的 2 级数据aboutToAppear():void{this.twoLevelData[];for(leti0;ithis.fullData.length;i){constprovthis.fullData[i];constcityList:RegionNode[][];if(prov.children){for(letj0;jprov.children.length;j){cityList.push({text:prov.children[j].text});// 不包含 children}}this.twoLevelData.push({text:prov.text,children:cityList});}this.updateAddress();}通过遍历原始数据并剥离城市节点下的children我们得到一份干净的 2 级级联结构。Toggle 开关切换时直接切换range的数据源即可。3.3 TextPicker 集成将数据接入 TextPicker根据showDistrict状态动态选择 2 级或 3 级数据TextPicker({range:this.showDistrict?this.fullData:this.twoLevelData,selected:this.showDistrict?this.selectedIdx:[this.selectedIdx[0],this.selectedIdx[1]],value:this.selectedVal}).onChange((value:string|string[],index:number|number[]){this.onPickerChange(value,index);})关键设计点2 级模式的selected数组长度是 2省、市3 级模式长度是 3省、市、区。切换模式时需要同步调整selected和value的数组长度。3.4 选择结果展示地址选择的结果展示在一个信息卡片中——显示当前选中的完整地址和对应的索引路径Column(){Row(){Text().fontSize(22).margin({right:10})Text(this.addressText).fontSize(18).fontColor(#1a1a2e).fontWeight(FontWeight.Bold)}Row(){Text(层级).fontSize(11).fontColor(#9999AA)Text(this.selectedIdx.join( → )).fontSize(11).fontColor(#9999AA)}.margin({top:8})}.width(100%).padding({left:Spacing.LG,right:Spacing.LG,top:14,bottom:14}).backgroundColor(#F0F6FF)卡片使用浅蓝底色#F0F6FF与页面其他区域区分地址文本使用大号加粗字体凸显选择结果索引路径作为辅助信息以灰色小字展示。3.5 快捷预设提供 6 个常用城市/区组合的快捷入口让用户一键跳转到常见地址Row(){this.PresetBtn(北京 · 朝阳,(){this.applyPreset(0,2,0);})this.PresetBtn(北京 · 海淀,(){this.applyPreset(0,3,0);})this.PresetBtn(上海 · 浦东,(){this.applyPreset(1,0,0);})}点击任意预设按钮调用applyPreset方法同时更新selectedIdx和selectedValapplyPreset(pIdx:number,cIdx:number,dIdx:number):void{this.selectedIdx[pIdx,cIdx,dIdx];constprovthis.fullData[pIdx].text;constcitythis.fullData[pIdx].children![cIdx].text;constdistthis.fullData[pIdx].children![cIdx].children![dIdx].text;this.selectedVal[prov,city,dist];this.updateAddress();}注意预设按钮使用Builder方法提取为可复用组件BuilderPresetBtn(label:string,onClick:()void){Text(label).fontSize(12).fontColor(#1677FF).fontWeight(FontWeight.Medium).padding({top:8,bottom:8,left:12,right:12}).borderRadius(8).backgroundColor(#EEF3FF).margin({right:8}).onClick(onClick)}3.6 层级切换使用 Toggle 开关在 2 级和 3 级之间动态切换Toggle({type:ToggleType.Switch,isOn:this.showDistrict}).onChange((on:boolean){this.showDistricton;this.selectedIdx[0,0,0];if(on){this.selectedVal[北京市,东城区,东华门街道];}else{this.selectedVal[北京市,东城区];}this.updateAddress();})切换时重置选中位置到第一项并根据新模式设置对应长度的 value 数组。四、级联原理与自定义联动TextPicker 的级联行为是自动的——当用户在第一列选择了一个新省份组件内部会查找该省份的children并更新第二列选项。但这仅限于组件内部。如果需要额外的自定义联动逻辑如在选择结果卡中实时更新、触发搜索等你需要在onChange回调中处理onPickerChange(value:string|string[],index:number|number[]):void{if(Array.isArray(value)){this.selectedValvalueasstring[];}if(Array.isArray(index)){this.selectedIdxindexasnumber[];}this.updateAddress();// 自定义逻辑更新结果展示}这里的类型判断Array.isArray(value)是因为onChange的参数类型是联合类型string | string[]。在级联模式下参数始终是数组类型即使只有 2 级时也是 2 元数组。五、完整交互流程初始状态显示 3 级级联选择器默认选中北京市 - 东城区 - 东华门街道结果卡片展示完整地址手动选择滑动第一列切换省份例如从北京市到广东省第二列自动变为广东省下的城市列表广州市、深圳市、东莞市、佛山市第三列相应更新切换层级关闭显示街道/镇开关选择器变为 2 级省 - 市第三列消失快捷预设点击深圳 · 南山按钮选择器自动跳转到广东省 - 深圳市 - 南山区打开层级重新打开开关回到 3 级模式继续精确到街道/镇级别六、注意事项6.1 数据完整性级联数据必须是完整的树形结构——每个节点的children要么全部存在要么全部不存在。不完整的结构如部分城市有区、部分没有可能导致级联行为异常。6.2 索引范围在 2 级和 3 级之间切换时selected索引数组的长度必须与级数匹配。3 级时需要 3 个索引2 级时需要 2 个。长度不匹配会导致运行时错误。6.3 数据规模TextPicker 会在内存中持有完整的级联数据。对于地址选择这类数据量适中的场景数百个省市、数千个区性能没有问题。但如果数据量极大如数十万条建议考虑异步加载方案。6.4 与 DatePicker 的区别TextPicker 和 DatePicker 虽然外观相似都是滚轮选择但用途完全不同DatePicker 专用于日期选择列固定为年/月/日数据由系统生成TextPicker 是通用选择器列数和数据完全由开发者定义七、总结TextPicker 是 ArkUI 中最灵活的选择器组件。从简单的单列选择性别、血型到复杂的多级级联地址、行业它都能胜任。其核心优势在于三种模式覆盖所有场景单列简单、多列独立、级联联动级联行为自动处理开发者只需提供树形数据无需手动实现联动逻辑灵活的显示控制通过 CSS 属性控制样式适应不同设计需求本文通过地址选择器这个完整的实战案例覆盖了 TextPicker 级联模式的核心用法——从数据构建到选择器集成、从结果展示到快捷预设、从层级切换到联动逻辑。掌握了这些技术你就能在任何需要层级化选择的场景中游刃有余。