今天我们来说一个非常好用的框架PickerView,来完成地址选择器的功能。还是老原则不好用,不推荐。先上个效果图。
1.首先我们来做准备工作。
添加依赖
compile 'com.contrarywind:Android-PickerView:3.2.5'
//里面有用到gson,如果原来项目中有无需添加gson
compile 'com.google.code.gson:gson:2.3.1'
添加gson的混淆
##---------------Begin: proguard configuration for Gson ----------
# Gson 代码混淆
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.daiba.wsjr.bean.** { *; }
##---------------End: proguard configuration for Gson ----------
在main文件夹下创建assets的文件夹用于放保存地址数据的json文件city.json。city.json文件里的内容会附在最后。效果如下。
然后免费送一个将json文件里的数据转换成json字符串的类。需要贴在项目里的偶。
public class GetJsonDataUtil {
public String getJson(Context context, String fileName) {
StringBuilder stringBuilder = new StringBuilder();
try {
AssetManager assetManager = context.getAssets();
BufferedReader bf = new BufferedReader(new InputStreamReader(
assetManager.open(fileName)));
String line;
while ((line = bf.readLine()) != null) {
stringBuilder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
}
最后在贴一个承载城市数据的类。
public class CityBean implements IPickerViewData {
/**
* province : 北京
* city_list : ["北京"]
*/
private String province;
private List city_list;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public List getCity_list() {
return city_list;
}
public void setCity_list(List city_list) {
this.city_list = city_list;
}
@Override
public String getPickerViewText() {
return this.province;
}
}
然后我们切入正题,先做好声明,省的你们粘完代码报错了,又说我都是按你的写的啊怎么报错呢?┭┮﹏┭┮
private ArrayList options1Items = new ArrayList<>();
private ArrayList> options2Items = new ArrayList<>();
private ArrayList>> options3Items = new ArrayList<>();
private ArrayList bankNameList = new ArrayList<>();
private Thread thread;
private static final int MSG_LOAD_DATA = 0x0001;
private static final int MSG_LOAD_SUCCESS = 0x0002;
private static final int MSG_LOAD_FAILED = 0x0003;
private boolean isLoaded = false;
private String province;
private String city;
private TextView bank_addr;
因为我们要加载json文件中的数据,这属于耗时操作需要一个子线程,数据加载完毕才能让选择器展示数据。这里免我们用到了Handle解决这个问题。
(往方法区粘就行)
//判断地址数据是否获取成功
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LOAD_DATA:
if (thread==null){//如果已创建就不再重新创建子线程了
Log.i("addr","地址数据开始解析");
thread = new Thread(new Runnable() {
@Override
public void run() {
// 写子线程中的操作,解析省市区数据
initJsonData();
}
});
thread.start();
}
break;
case MSG_LOAD_SUCCESS:
Log.i("addr","地址数据获取成功");
isLoaded = true;
break;
case MSG_LOAD_FAILED:
Log.i("addr","地址数据获取失败");
break;
}
}
};
下面的是刚才用到的解析数据的工具类
private void initJsonData() {//解析数据
/**
* 注意:assets 目录下的Json文件仅供参考,实际使用可自行替换文件
* 关键逻辑在于循环体
*
* */
String CityData = new GetJsonDataUtil().getJson(this,"city.json");//获取assets目录下的json文件数据
ArrayList jsonBean = parseData(CityData);//用Gson 转成实体
/**
* 添加省份数据
*
* 注意:如果是添加的JavaBean实体,则实体类需要实现 IPickerViewData 接口,
* PickerView会通过getPickerViewText方法获取字符串显示出来。
*/
options1Items = jsonBean;
for (int i=0;i CityList = new ArrayList<>();//该省的城市列表(第二级)
ArrayList> Province_AreaList = new ArrayList<>();//该省的所有地区列表(第三极)
for (int c=0; c parseData(String result) {//Gson 解析
ArrayList detail = new ArrayList<>();
try {
JSONArray data = new JSONArray(result);
Gson gson = new Gson();
for (int i = 0; i < data.length(); i++) {
CityBean entity = gson.fromJson(data.optJSONObject(i).toString(), CityBean.class);
detail.add(entity);
}
} catch (Exception e) {
e.printStackTrace();
mHandler.sendEmptyMessage(MSG_LOAD_FAILED);
}
return detail;
}
最后一个是弹出地址选择器的类
private void ShowPickerView() {// 弹出地址选择器
OptionsPickerView pvOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
//返回的分别是三个级别的选中位置
province = options1Items.get(options1).getPickerViewText();
city = options2Items.get(options1).get(options2);
// + options3Items.get(options1).get(options2).get(options3);
bank_addr.setText(province+city);
}
})
.setDividerColor(Color.BLACK)
.setTextColorCenter(Color.BLACK) //设置选中项文字颜色
.setContentTextSize(20)
.setOutSideCancelable(false)// default is true
.build();
pvOptions.setPicker(options1Items, options2Items);//二级选择器(市区)
//pvOptions.setPicker(options1Items, options2Items, options3Items);//三级选择器
pvOptions.show();
}
然后我们在onCreate方法里启动刚才的handle线程
mHandler.sendEmptyMessage(MSG_LOAD_DATA);
大功告成。
city.json的文件忘记给大家了放在下面了,把他粘贴在文本文档里把文本文档的后缀名改成.json就变成json文件了。
city.json
[
{
"province": "北京",
"city_list": [
"北京"
]
},
{
"province": "天津",
"city_list": [
"天津"
]
},
{
"province": "河北",
"city_list": [
"保定",
"唐山",
"廊坊",
"张家口",
"承德",
"沧州",
"石家庄",
"秦皇岛",
"衡水",
"邢台",
"邯郸"
]
},
{
"province": "山西",
"city_list": [
"临汾",
"吕梁",
"大同",
"太原",
"忻州",
"晋中",
"晋城",
"朔州",
"运城",
"长治",
"阳泉"
]
},
{
"province": "内蒙古",
"city_list": [
"乌兰察布",
"乌海",
"兴安",
"包头",
"呼伦贝尔",
"呼和浩特",
"巴彦淖尔",
"赤峰",
"通辽",
"鄂尔多斯",
"锡林郭勒",
"阿拉善"
]
},
{
"province": "辽宁",
"city_list": [
"丹东",
"大连",
"抚顺",
"朝阳",
"本溪",
"沈阳",
"盘锦",
"营口",
"葫芦岛",
"辽阳",
"铁岭",
"锦州",
"阜新",
"鞍山"
]
},
{
"province": "吉林",
"city_list": [
"吉林",
"四平",
"延边",
"松原",
"白城",
"白山",
"辽源",
"通化",
"长春"
]
},
{
"province": "黑龙江",
"city_list": [
"七台河",
"伊春",
"佳木斯",
"双鸭山",
"哈尔滨",
"大兴安岭",
"大庆",
"牡丹江",
"绥化",
"鸡西",
"鹤岗",
"黑河",
"齐齐哈尔"
]
},
{
"province": "上海",
"city_list": [
"上海"
]
},
{
"province": "江苏",
"city_list": [
"南京",
"南通",
"宿迁",
"常州",
"徐州",
"扬州",
"无锡",
"泰州",
"淮安",
"盐城",
"苏州",
"连云港",
"镇江"
]
},
{
"province": "浙江",
"city_list": [
"丽水",
"台州",
"嘉兴",
"宁波",
"杭州",
"温州",
"湖州",
"绍兴",
"舟山",
"衢州",
"金华"
]
},
{
"province": "安徽",
"city_list": [
"亳州",
"六安",
"合肥",
"安庆",
"宣城",
"宿州",
"池州",
"淮北",
"淮南",
"滁州",
"芜湖",
"蚌埠",
"铜陵",
"阜阳",
"马鞍山",
"黄山"
]
},
{
"province": "福建",
"city_list": [
"三明",
"南平",
"厦门",
"宁德",
"泉州",
"漳州",
"福州",
"莆田",
"龙岩"
]
},
{
"province": "江西",
"city_list": [
"上饶",
"九江",
"南昌",
"吉安",
"宜春",
"抚州",
"新余",
"景德镇",
"萍乡",
"赣州",
"鹰潭"
]
},
{
"province": "山东",
"city_list": [
"东营",
"临沂",
"威海",
"德州",
"日照",
"枣庄",
"泰安",
"济南",
"济宁",
"淄博",
"滨州",
"潍坊",
"烟台",
"聊城",
"莱芜",
"菏泽",
"青岛"
]
},
{
"province": "河南",
"city_list": [
"三门峡",
"信阳",
"南阳",
"周口",
"商丘",
"安阳",
"平顶山",
"开封",
"新乡",
"洛阳",
"漯河",
"濮阳",
"焦作",
"省直辖",
"许昌",
"郑州",
"驻马店",
"鹤壁"
]
},
{
"province": "湖北",
"city_list": [
"十堰",
"咸宁",
"孝感",
"宜昌",
"恩施",
"武汉",
"省直辖",
"荆州",
"荆门",
"襄阳",
"鄂州",
"随州",
"黄冈",
"黄石"
]
},
{
"province": "湖南",
"city_list": [
"娄底",
"岳阳",
"常德",
"张家界",
"怀化",
"株洲",
"永州",
"湘潭",
"湘西",
"益阳",
"衡阳",
"邵阳",
"郴州",
"长沙"
]
},
{
"province": "广东",
"city_list": [
"东莞",
"中山",
"云浮",
"佛山",
"广州",
"惠州",
"揭阳",
"梅州",
"汕头",
"汕尾",
"江门",
"河源",
"深圳",
"清远",
"湛江",
"潮州",
"珠海",
"肇庆",
"茂名",
"阳江",
"韶关"
]
},
{
"province": "广西",
"city_list": [
"北海",
"南宁",
"崇左",
"来宾",
"柳州",
"桂林",
"梧州",
"河池",
"玉林",
"百色",
"贵港",
"贺州",
"钦州",
"防城港"
]
},
{
"province": "海南",
"city_list": [
"三亚",
"海口",
"省直辖"
]
},
{
"province": "重庆",
"city_list": [
"重庆"
]
},
{
"province": "四川",
"city_list": [
"乐山",
"内江",
"凉山",
"南充",
"宜宾",
"巴中",
"广元",
"广安",
"德阳",
"成都",
"攀枝花",
"泸州",
"甘孜",
"眉山",
"绵阳",
"自贡",
"资阳",
"达州",
"遂宁",
"阿坝",
"雅安"
]
},
{
"province": "贵州",
"city_list": [
"六盘水",
"安顺",
"毕节",
"贵阳",
"遵义",
"铜仁",
"黔东南",
"黔南",
"黔西南"
]
},
{
"province": "云南",
"city_list": [
"临沧",
"丽江",
"保山",
"大理",
"德宏",
"怒江",
"文山",
"昆明",
"昭通",
"普洱",
"曲靖",
"楚雄",
"玉溪",
"红河",
"西双版纳",
"迪庆"
]
},
{
"province": "西藏",
"city_list": [
"山南",
"拉萨",
"日喀则",
"昌都",
"林芝",
"那曲",
"阿里"
]
},
{
"province": "陕西",
"city_list": [
"咸阳",
"商洛",
"安康",
"宝鸡",
"延安",
"榆林",
"汉中",
"渭南",
"西安",
"铜川"
]
},
{
"province": "甘肃",
"city_list": [
"临夏",
"兰州",
"嘉峪关",
"天水",
"定西",
"平凉",
"庆阳",
"张掖",
"武威",
"甘南",
"白银",
"酒泉",
"金昌",
"陇南"
]
},
{
"province": "青海",
"city_list": [
"果洛",
"海东",
"海北",
"海南",
"海西",
"玉树",
"西宁",
"黄南"
]
},
{
"province": "宁夏",
"city_list": [
"中卫",
"吴忠",
"固原",
"石嘴山",
"银川"
]
},
{
"province": "新疆",
"city_list": [
"乌鲁木齐",
"伊犁",
"克孜勒苏",
"克拉玛依",
"区直辖",
"博尔塔拉",
"吐鲁番",
"和田",
"哈密",
"喀什",
"塔城",
"巴音郭楞",
"昌吉",
"阿克苏",
"阿勒泰"
]
}
]