鴻蒙(HarmonyOS) - 實現省市區三級聯動
電商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組件的基礎用法參考官方文檔:
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=""http://選中的省份
@State selectCity:string=""http://選中的城市
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使用案例的工具庫,后續會陸續增加功能以及維護。

浙公網安備 33010602011771號