鸿蒙(HarmonyOS) – 实现省市区三级联动-牛翰网

鸿蒙(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组件的基础用法参考官方文档:

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

请登录后发表评论

    没有回复内容