您的位置:首页 > 移动开发 > Android开发

史上最好用的Android省市区选择,三级联动

2018-01-09 21:06 453 查看
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,即可拿到结果。

模拟器上获取不到数据,所以没有显示,在真机上是可以正常获取数据的

代码地址:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐