项目需求要实现省市二级联动,因为一直没有定样式,所以一直没有开动,但是ios小伙伴先给搞定了,没办法就照着他的样式来写一个吧,
首先看下效果吧,没有加以美化选中效果....
主要是用PopupWindows来实现了省市的二级联动,xml文件很齐全,就捎带把区也写了进去..但是没有实现,有兴趣的小伙伴可以挑战一下,有了之前的省联动市.应该很容易就实现三级联动了.
首先要把xml本地文件添加到项目中(花了两个币下载的真坑),新建一个assets文件夹把省市区文件放进去即可(后面我会上传的)
我们先开始解析这个省市区文件代码如下
public void initProvinceDatas() {
List<Provinces> provinceList = null;
AssetManager asset = activity.getAssets();
try {
InputStream input = asset.open("province_data.xml");
// 创建一个解析xml的工厂对象
SAXParserFactory spf = SAXParserFactory.newInstance();
// 解析xml
SAXParser parser = spf.newSAXParser();
XmlParserHandler handler = new XmlParserHandler();
parser.parse(input, handler);
input.close();
// 获取解析出来的数据
provinceList = handler.getDataList();
//*/ 初始化默认选中的省、市、区
if (provinceList != null && !provinceList.isEmpty()) {
mCurrentProviceName = provinceList.get(0).getProvince();
mCurrentProviceID = provinceList.get(0).getProvince_id();
List<Citys> cityList = provinceList.get(0).getCitysList();
if (cityList != null && !cityList.isEmpty()) {
mCurrentCityName = cityList.get(0).getCity();
List<Area> districtList = cityList.get(0).getAreaList();
mCurrentDistrictName = districtList.get(0).getArea();
}
}
//*/
mProvinceDatas = new String[provinceList.size()];
mProvinceDatasID = new String[provinceList.size()];
for (int i = 0; i < provinceList.size(); i++) {
// 遍历所有省的数据
mProvinceDatas[i] = provinceList.get(i).getProvince();
mProvinceDatasID[i] = provinceList.get(i).getProvince_id();
List<Citys> cityList = provinceList.get(i).getCitysList();
String[] cityNames = new String[cityList.size()];
String[] cityId = new String[cityList.size()];
for (int j = 0; j < cityList.size(); j++) {
// 遍历省下面的所有市的数据
cityNames[j] = cityList.get(j).getCity();
cityId[j] = cityList.get(j).getCity_id();
List<Area> districtList = cityList.get(j).getAreaList();
String[] distrinctNameArray = new String[districtList.size()];
for (int k = 0; k < districtList.size(); k++) {
// 遍历市下面所有区/县的数据
Area districtModel = new Area(districtList.get(k).getArea(), districtList.get(k).getArea_id());
// // 区/县对于的邮编,保存到mZipcodeDatasMap
// mZipcodeDatasMap.put(districtList.get(k).getName(), districtList.get(k).getZipcode());
// distrinctArray[k] = districtModel;
// distrinctNameArray[k] = districtModel.getName();
}
// 市-区/县的数据,保存到mDistrictDatasMap
mDistrictDatasMap.put(cityNames[j], distrinctNameArray);
mDistrictDatasMap.put(cityId[j], distrinctNameArray);
}
// 省-市的数据,保存到mCitisDatasMap
mCitisDatasMap.put(provinceList.get(i).getProvince(), cityNames);
mCitisDatasIDMap.put(provinceList.get(i).getProvince(), cityId);
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
}
}
关于Xml解析可以查看下面资料
(使用SAX解析)
(使用DOM解析)
此次项目中使用的是SAX解析方式,因为它占用内存少,并且速度快,数据解析代码写在了 XmlParserHandler.Java中,代码如下:
package com.mostchh.scienceploatform.utils;
import com.mostchh.scienceploatform.model.home.Area;
import com.mostchh.scienceploatform.model.home.Citys;
import com.mostchh.scienceploatform.model.home.Provinces;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
public class XmlParserHandler extends DefaultHandler {
/**
* 存储所有的解析对象
*/
private List<Provinces> provinceList = new ArrayList<Provinces>();
public XmlParserHandler() {
}
public List<Provinces> getDataList() {
return provinceList;
}
@Override
public void startDocument() throws SAXException {
// 当读到第一个开始标签的时候,会触发这个方法
}
Provinces provinceModel = new Provinces();
Citys cityModel = new Citys();
Area districtModel = new Area();
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// 当遇到开始标记的时候,调用这个方法
if (qName.equals("province")) {
provinceModel = new Provinces();
provinceModel.setProvince(attributes.getValue(0));
provinceModel.setProvince_id(attributes.getValue(1));
provinceModel.setCitysList(new ArrayList<Citys>());
} else if (qName.equals("city")) {
cityModel = new Citys();
cityModel.setCity(attributes.getValue(0));
cityModel.setCity_id(attributes.getValue(1));
cityModel.setAreaList(new ArrayList<Area>());
} else if (qName.equals("district")) {
districtModel = new Area();
districtModel.setArea(attributes.getValue(0));
// districtModel.setZipcode(attributes.getValue(1));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// 遇到结束标记的时候,会调用这个方法
if (qName.equals("district")) {
cityModel.getAreaList().add(districtModel);
} else if (qName.equals("city")) {
provinceModel.getCitysList().add(cityModel);
} else if (qName.equals("province")) {
provinceList.add(provinceModel);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
}
}
然后是PopupWindows的xml文件我用两个RecyclerView来实现他们的联动效果.如果对PopupWindows和RecyclerView不熟悉的同学就去找找资料,在这就不赘述了...主要就是数据的适配,首先获得省级列表之后要对外释放一个接口给市级列表,然后在对市级列表进行相应的适配.把之前获得的省市MAp,当前省级名称都传过去.
/**
* 点击省切换市区
*/
@Override
public void onPopProvinceItemClicked(int position) {
cityPopWindowsAdaptersAdapter = new CityPopWindowsAdapter(activity);
cityPopRecycler.setAdapter(cityPopWindowsAdaptersAdapter);
mCurrentProviceName = mProvinceDatas[position];
mCurrentProviceID = mProvinceDatasID[position];
cityPopWindowsAdaptersAdapter.setData(mCitisDatasMap, mCurrentProviceName, this);
}
要注意cityPopWindowsAdapter返回的list是
mCitisDatasMap.get(provinceStr).length
主要是参考了 这篇博客,在此感谢,此片博客实现了Wheel滑动的省市区三级联动有需要的小伙伴可以去看看
我会专门写一个Demo上传便于小伙伴们查阅
Demo下载地址