最好用的Android省市区三级联动选择效果
时间:2021-01-13 09:58:51|栏目:Android代码|点击: 次
Android省市区选择三级联动效果,一个不大不小的功能,就算你做过,但是没有相关的代码直接写,也要花掉你至少半天时间。
下面我写出我的实现过程(思路绝对清晰)。
先上效果图
一、准备数据
我是用的本地的json数据(走网络的话太慢,每次都要请求),放在asserts中。格式如下:
[{ "name": "河北省", "city": [ { "name": "石家庄市", "area": [ "长安区", "桥东区", "桥西区", "新华区", "郊 区", "井陉矿区", "井陉县", "正定县", "栾城县", "行唐县", "灵寿县", "高邑县", "深泽县", "赞皇县", "无极县", "平山县", "元氏县", "赵 县", "辛集市", "藁", "晋州市", "新乐市", "鹿泉市" ] },......]
二、解析数据
首先根据json生成Province对象
然后通过getAssets().open("citylist.json");获取文件输入流,接着转成字节,最终获取字符串。
然后用Gson解析字符串得到Province的List对象。由于读文件是IO操作,这里我用了RxJava,代码如下:
/** * 从assert文件夹中获取json数据 */ private void initJsonData() { Observable.create(new ObservableOnSubscribe<List<Province>>() { @Override public void subscribe(ObservableEmitter<List<Province>> emitter) throws Exception { List<Province> provinces = new ArrayList<>(); try { StringBuffer sb = new StringBuffer(); InputStream is = getAssets().open("citylist.json");//打开json数据 byte[] by = new byte[is.available()];//转字节 int len = -1; while ((len = is.read(by)) != -1) { sb.append(new String(by, 0, len, "utf8"));//根据字节长度设置编码 } is.close();// 关闭流 // 通过Gson将字符串转成对象list Gson gson = new Gson(); provinces = gson.fromJson(sb.toString(), new TypeToken<List<Province>>() { }.getType()); } catch (Exception e) { e.printStackTrace(); } finally { emitter.onNext(provinces); } } }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<List<Province>>() { @Override public void accept(List<Province> provinces) throws Exception { if (provinces != null && provinces.size() > 0) { RegionSelectActivity.this.provinces = provinces; // 显示数据 showData(); } } }); }
三、显示数据
RxJava异步读取数据后就可以显示了,这里用了三个Spinner来分别显示省,市,区数据。
显示的思路大家都清楚,这里不再赘述,代码如下
/** * 展示数据 */ private void showData() { for (Province province : provinces) { provinceList.add(province.getName()); } // 显示省份数据 spProvince.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, provinceList)); spProvince.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { provincePosition = position; provinceName = provinceList.get(position); // 获取当前省份对应的城市list cityList.clear(); List<Province.CityBean> cityBeans = provinces.get(position).getCity(); for (Province.CityBean city : cityBeans) { cityList.add(city.getName()); } // 刷新城市列表 spCity.setSelection(0); cityName = cityList.get(0); cityAdapter.notifyDataSetChanged(); // 刷新城区列表 updateArea(0); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); // 显示城市数据 spCity.setAdapter(cityAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, cityList)); spCity.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { cityPosition = position; cityName = cityList.get(position); // 刷新城区列表 updateArea(position); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); // 显示城区数据 spArea.setAdapter(areaAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, areaList)); spArea.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { areaName = areaList.get(position); } @Override public void onNothingSelected(AdapterView<?> parent) { } });
四、高德地图获取当前城市
调用了高德地图,抽象成了BaseLocationActivity,用的时候只需要继承自它,然后实现抽象方法LocationResult,即可拿到结果。
模拟器上获取不到数据,所以没有显示,在真机上是可以正常获取数据的
代码地址:下载地址。