首先咱们看一下要实现的效果。

Android中省市区三级联动的地方用的很多,尤其是在商场项目中用来作为地址选择,现在为大家提供几种实现的方式,大家可根据自己的需求自行选择。
一、assets目录下xml文件实现
1、assets目录下放好xml文件,文件中类型如下:

2、github上面有一个叫做 android-wheel 的开源控件,我们需要下载然后import到项目中。
File -> New -> Import Module,然后F4->Dependencies->+ Module dependencies
!!!在清单文件application下添加 tools:replace="android:theme,android:label",
否则运行的时候容易出错。
3、布局文件使用该控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aigestudio="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:background="@color/mainColor"
android:layout_width="match_parent"
android:layout_height="44dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_cancel"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:paddingLeft="@dimen/toolbar_padLeft"
android:paddingRight="@dimen/toolbar_padLeft"
android:paddingTop="20px"
android:paddingBottom="20px">
<TextView
android:gravity="center"
android:text="取消"
android:textSize="15sp"
android:textColor="#fff"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<TextView
android:id="@+id/pickerTitleId"
android:layout_centerInParent="true"
android:text="所在地区"
android:gravity="center"
android:textSize="15sp"
android:textColor="#fff"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_confirm"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingLeft="@dimen/toolbar_padLeft"
android:paddingRight="@dimen/toolbar_padLeft"
android:paddingTop="20px"
android:paddingBottom="20px">
<TextView
android:text="完成"
android:gravity="center"
android:textSize="15sp"
android:textColor="#fff"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
android:orientation="horizontal">
<kankan.wheel.widget.WheelView
android:background="#fff"
android:id="@+id/id_province"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
</kankan.wheel.widget.WheelView>
<kankan.wheel.widget.WheelView
android:background="#fff"
android:id="@+id/id_city"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
</kankan.wheel.widget.WheelView>
<kankan.wheel.widget.WheelView
android:background="#fff"
android:id="@+id/id_area"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" >
</kankan.wheel.widget.WheelView>
</LinearLayout>
</LinearLayout>
4、解析assets下province_data.xml文件
protected void initProvinceDatas() {
List provinceList = null;
AssetManager asset = this.getAssets();
try {
InputStream e = asset.open("province_data.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
XmlParserHandler handler = new XmlParserHandler();
parser.parse(e, handler);
e.close();
provinceList = handler.getDataList();
List cityList;
if(provinceList != null && !provinceList.isEmpty()) {
this.mCurrentProviceName = ((ProvinceModel)provinceList.get(0)).getName();
List i = ((ProvinceModel)provinceList.get(0)).getCityList();
if(i != null && !i.isEmpty()) {
this.mCurrentCityName = ((CityModel)i.get(0)).getName();
cityList = ((CityModel)i.get(0)).getDistrictList();
this.mCurrentDistrictName = ((DistrictModel)cityList.get(0)).getName();
this.mCurrentZipCode = ((DistrictModel)cityList.get(0)).getZipcode();
}
}
this.mProvinceDatas = new String[provinceList.size()];
this.proAreaIds = new String[provinceList.size()];
for(int var17 = 0; var17 < provinceList.size(); ++var17) {
this.mProvinceDatas[var17] = ((ProvinceModel)provinceList.get(var17)).getName();
this.proAreaIds[var17] = ((ProvinceModel) provinceList.get(var17)).getArea_id();
cityList = ((ProvinceModel)provinceList.get(var17)).getCityList();
String[] cityNames = new String[cityList.size()];
String[] cityAreaIds = new String[cityList.size()];
for(int j = 0; j < cityList.size(); ++j) {
cityNames[j] = ((CityModel)cityList.get(j)).getName();
cityAreaIds[j]=((CityModel) cityList.get(j)).getArea_id();
List districtList = ((CityModel)cityList.get(j)).getDistrictList();
String[] distrinctNameArray = new String[districtList.size()];
String[] distrinctAreaId = new String[districtList.size()];
DistrictModel[] distrinctArray = new DistrictModel[districtList.size()];
for(int k = 0; k < districtList.size(); ++k) {
DistrictModel districtModel = new DistrictModel(((DistrictModel)districtList.get(k)).getName(), ((DistrictModel)districtList.get(k)).getZipcode(),((DistrictModel)districtList.get(k)).getArea_id());
this.mZipcodeDatasMap.put(((DistrictModel)districtList.get(k)).getName(), ((DistrictModel)districtList.get(k)).getZipcode());
distrinctArray[k] = districtModel;
distrinctNameArray[k] = districtModel.getName();
distrinctAreaId[k] = districtModel.getArea_id();
}
this.mDistrictDatasMap.put(cityNames[j], distrinctNameArray);
this.distAreaIdMap.put(cityNames[j],distrinctAreaId);
}
this.mCitisDatasMap.put(((ProvinceModel)provinceList.get(var17)).getName(), cityNames);
this.cityAreaIdMap.put(((ProvinceModel) provinceList.get(var17)).getName(),cityAreaIds);
}
} catch (Throwable var16) {
var16.printStackTrace();
}
}
5、设置市级数据
private void updateCities() {
int pCurrent = this.mViewProvince.getCurrentItem();
this.mCurrentProviceName = this.mProvinceDatas[pCurrent];
String[] cities = (String[])this.mCitisDatasMap.get(this.mCurrentProviceName);
if(cities == null) {
cities = new String[]{""};
}
this.mViewCity.setViewAdapter(new ArrayWheelAdapter(this, cities,15,14));
this.mViewCity.setCurrentItem(0);
this.updateAreas();
}
6、设置区级数据
private void updateAreas() {
int pCurrent = this.mViewCity.getCurrentItem();
this.mCurrentCityName = ((String[])this.mCitisDatasMap.get(this.mCurrentProviceName))[pCurrent];
String[] areas = (String[])this.mDistrictDatasMap.get(this.mCurrentCityName);
if(areas == null) {
areas = new String[]{""};
}
this.mViewDistrict.setViewAdapter(new ArrayWheelAdapter(this, areas,15,14));
this.mViewDistrict.setCurrentItem(0);
}
7、初始化控件
private void initAreaPicker() {
mAreaPicker = View.inflate(this,R.layout.picker_area_layout,null);
mViewProvince = ((WheelView) mAreaPicker.findViewById(R.id.id_province));
mViewCity = ((WheelView) mAreaPicker.findViewById(R.id.id_city));
mViewDistrict = ((WheelView) mAreaPicker.findViewById(R.id.id_area));
mViewProvince.setVisibleItems(7);
mViewCity.setVisibleItems(7);
mViewDistrict.setVisibleItems(7);
mViewProvince.addChangingListener(this);
mViewCity.addChangingListener(this);
mViewDistrict.addChangingListener(this);
RelativeLayout tv_cancelStart = ((RelativeLayout) mAreaPicker.findViewById(R.id.tv_cancel));
RelativeLayout tv_confirmStart = ((RelativeLayout) mAreaPicker.findViewById(R.id.tv_confirm));
tv_cancelStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPopTime != null){
mPopTime.dismiss();
}
}
});
tv_confirmStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentProPosition = newProPosition;
currentCityPosition = newCityPosition;
currentDisPosition = newDisPosition;
MainActivity.this.mCurrentProviceName = mProvinceDatas[currentProPosition];
MainActivity.this.mCurrentCityName = ((String[])MainActivity.this.mCitisDatasMap.get(MainActivity.this.mCurrentProviceName))[currentCityPosition];
String[] disNames = ((String[])MainActivity.this.mDistrictDatasMap.get(MainActivity.this.mCurrentCityName));
if(disNames!=null && disNames.length > currentDisPosition){
MainActivity.this.mCurrentDistrictName = disNames[currentDisPosition];
}else{
mCurrentDistrictName = "";
}
areaTv.setText(mCurrentProviceName+" "+mCurrentCityName+" "+mCurrentDistrictName);
if (mPopTime != null){
mPopTime.dismiss();
}
}
});
}
8、下面来看一下效果
给WheelView设置的适配器中有两个参数:
new ArrayWheelAdapter<>(this, mProvinceDatas,15,14)
15:item上下间距
14:字体大小

二、assets目录下json数据解析
如果后台提供的是json数据,如本项目中的json解析,可以用三层for循环来解析,之后的操作就容易了。
json数据如下:

1、解析json数据
for (int i = 0; i < areaDataEntity.getData().size(); i++) {
List<ProvinceModel> provinceModelList = new ArrayList<>();
CountryModel countryModel = new CountryModel();
AreaDataEntity.DataBean dataBean = areaDataEntity.getData().get(i);
countryModel.setArea_id(dataBean.getRegion_id()+"");
countryModel.setName(dataBean.getRegion_name());
for (int j = 0; j < dataBean.getChild().size(); j++) {
List<CityModel> cityModelList = new ArrayList<>();
ProvinceModel provinceModel = new ProvinceModel();
AreaDataEntity.DataBean.ChildBeanXX childBean = dataBean.getChild().get(j);
provinceModel.setName(childBean.getRegion_name());
provinceModel.setArea_id(childBean.getRegion_id()+"");
for (int k = 0; k < childBean.getChild().size(); k++) {
List<DistrictModel> districtModelList = new ArrayList<>();
CityModel cityModel = new CityModel();
AreaDataEntity.DataBean.ChildBeanXX.ChildBeanX childCityBean = childBean.getChild().get(k);
cityModel.setName(childCityBean.getRegion_name());
cityModel.setArea_id(childCityBean.getRegion_id()+"");
if(childCityBean.getChild()==null){
cityModelList.add(cityModel);
continue;
}
for (int m = 0; m < childCityBean.getChild().size(); m++) {
DistrictModel districtModel = new DistrictModel();
AreaDataEntity.DataBean.ChildBeanXX.ChildBeanX.ChildBean childDisBean = childCityBean.getChild().get(m);
districtModel.setArea_id(childDisBean.getRegion_id()+"");
districtModel.setName(childDisBean.getRegion_name());
districtModelList.add(districtModel);
}
cityModel.setDistrictList(districtModelList);
cityModelList.add(cityModel);
}
provinceModel.setCityList(cityModelList);
provinceModelList.add(provinceModel);
}
countryModel.setProvinceList(provinceModelList);
countryList.add(countryModel);
}
2、本项目还提供了json解析四级地区联动,需要的可以参考。

三、导入依赖,直接使用控件
1、导入依赖
compile 'liji.library.dev:citypickerview:0.7.0'
2、代码中直接使用该控件
private void selectAddress() {
CityPicker cityPicker = new CityPicker.Builder(Main2Activity.this)
.textSize(14)
.title("地址选择")
.titleBackgroundColor("#FFFFFF")
.confirTextColor("#696969")
.cancelTextColor("#696969")
.province("江苏省")
.city("常州市")
.district("天宁区")
.textColor(Color.parseColor("#000000"))
.provinceCyclic(false)
.cityCyclic(false)
.districtCyclic(false)
.visibleItemsCount(7)
.itemPadding(20)
.onlyShowProvinceAndCity(false)
.build();
cityPicker.show();
//监听方法,获取选择结果
cityPicker.setOnCityItemClickListener(new CityPicker.OnCityItemClickListener() {
@Override
public void onSelected(String... citySelected) {
//省份
String province = citySelected[0];
//城市
String city = citySelected[1];
//区县(如果设定了两级联动,那么该项返回空)
String district = citySelected[2];
//邮编
String code = citySelected[3];
//为TextView赋值
areaTv.setText(province.trim() + "-" + city.trim() + "-" + district.trim());
}
});
}
想看效果扫描以下二维码安装apk。【各位小可爱们如果觉得效果需要,可以小小的赞赏一下~~么么哒】

网友评论