电商App在填写收货地址时,需要用户选择省市区,今天我们使用鸿蒙自带的TextPicker组件实现省市区三级联动。
效果图如下:
数据准备
Github上有一个开源项目,支持中华人民共和国行政区划(五级):省级、地级、县级、乡级和村级,数据很全,并且很新,支持不同的组合,json数据格式跟sqlite3数据库格式。
Github地址:
https://github.com/modood/Administrative-divisions-of-China/tree/master
本案例中只下载“省份、城市”的Json数据,复制到项目的rawfile文件夹下,举例:
项目名称/entry/src/main/resources/rawfile/pc.json
封装三级联动弹窗组件
封装一个自定义弹窗组件,在aboutToAppear方法中初始化数据。
aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
@CustomDialog
export default struct SelectRegionDialog {
controller: CustomDialogController
map: Map<string, string[]> = new Map<string, string[]>();//省市数据
@State selectProvince:string=''//选择的省份
selectCity:string=''//选中的城市
confirm!: (province:string,city:string) => void //确定按钮点击回调
aboutToAppear(): void {
this.initData();
}
build() {
...
}
//初始化数据
initData(){
let result=AppUtil.getRawFileContent(this,'pc.json');//获取json字符串
let jsonObj: Record<string, Object> = JSON.parse(result);//解析称对象
let newMap: Map<string, object> = new Map<string, object>(Object.entries(jsonObj));
newMap.forEach((value, key) => {
let valueData = value as string[];
this.map.set(key,valueData);//key value格式存储到map中
})
}
//获取省份字符串数组
getProvinceStrList(){
let keysArray: string[] = Array.from(this.map.keys());
return keysArray;
}
//获取城市字符串数组
getCityStrList(){
let cityList=this.map.get(this.selectProvince);
return cityList;
}
}
SelectRegionDialog自定义弹窗中的UI布局也简单,使用Row布局放两个TextPicker组件,宽度各占屏幕的50%,在省份的onChange方法中,当然省份的第一个城市默认选中。
TextPicker组件的基础用法参考官方文档:
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V2/ts-basic-components-textpicker-0000001427744824-V2
build() {
Column(){
Row(){
Button("取消").onClick(event=>{
this.controller.close();
})
Blank().layoutWeight(1)
Button("确定").onClick(event=>{
this.confirm(this.selectProvince,this.selectCity);
this.controller.close();
})
}.margin({
left:15,right:15,top:30
})
Row(){
TextPicker({ range: this.getProvinceStrList(), value: this.selectProvince })
.onChange((value: string|string[], index: number| number[]) => {
this.selectProvince = Array.isArray(value) ? value[0] : value;
//省份改变,默认选择第一个城市
let cityList=this.map.get(this.selectProvince);
if (cityList != null && cityList?.length>0){
this.selectCity = cityList[0];
}
}).width('50%')
.canLoop(false)//是否循环
.textStyle({
color:'#888888'
}).selectedTextStyle({
color:$r('app.color.title_color')
})
TextPicker({ range: this.getCityStrList(), value: this.selectCity })
.onChange((value: string|string[], index: number| number[]) => {
this.selectCity = Array.isArray(value) ? value[0] : value;
}).width('50%').canLoop(false).textStyle({
color:'#888888'
}).selectedTextStyle({
color:$r('app.color.title_color')
})
}.margin({
top:30,bottom:30
})
}
}
弹窗使用
选中的省份跟城市字段用@State修饰,这样当字符串变化时会刷新UI界面,使用CustomDialogController显示自定义弹窗,用户点击【选择省市区】按钮,显示对话框。
@Entry
@Component
struct SelectRegionPage {
@State selectProvince:string=""//选中的省份
@State selectCity:string=""//选中的城市
selectRegionDialog: CustomDialogController = new CustomDialogController({
builder: SelectRegionDialog({
selectProvince:this.selectProvince,
selectCity:this.selectCity,
confirm:this.onConfirm.bind(this)
}),
alignment: DialogAlignment.Bottom, // 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示
cornerRadius:{
topLeft:13,topRight:13,bottomLeft:0,bottomRight:0
},
autoCancel:false,
width:'100%'
})
build() {
Column(){
HdNav({
title:"省市区三级联动"
})
Text(this.selectProvince+this.selectCity).fontColor($r('app.color.title_color')).fontSize(24).margin({
top:150
})
Button("选择省市区").onClick(event=>{
this.onSelectRegion();
}).margin({
top:20
})
}
}
onSelectRegion(){
this.selectRegionDialog.open();
}
onConfirm(province:string,city:string){
this.selectProvince = province;
this.selectCity = city;
}
}
源码下载
这个案例的代码都提交到github上了,这个库我会一直维护,这个一个鸿蒙API使用案例的工具库,后续会陆续增加功能以及维护。
https://github.com/ansen666/harmony_tools
没有回复内容