利用PickerView完成地址选择器(省市二级联动)

今天我们来说一个非常好用的框架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<String> city_list;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public List<String> getCity_list() {
        return city_list;
    }

    public void setCity_list(List<String> city_list) {
        this.city_list = city_list;
    }

    @Override
    public String getPickerViewText() {
        return this.province;
    }
}

然后我们切入正题,先做好声明,省的你们粘完代码报错了,又说我都是按你的写的啊怎么报错呢?┭┮﹏┭┮

private ArrayList<CityBean> options1Items = new ArrayList<>();
    private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
    private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();
    private ArrayList<String> 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<CityBean> jsonBean = parseData(CityData);//用Gson 转成实体

        /**
         * 添加省份数据
         *
         * 注意:如果是添加的JavaBean实体,则实体类需要实现 IPickerViewData 接口,
         * PickerView会通过getPickerViewText方法获取字符串显示出来。
         */
        options1Items = jsonBean;

        for (int i=0;i<jsonBean.size();i++){//遍历省份
            ArrayList<String> CityList = new ArrayList<>();//该省的城市列表(第二级)
            ArrayList<ArrayList<String>> Province_AreaList = new ArrayList<>();//该省的所有地区列表(第三极)

            for (int c=0; c<jsonBean.get(i).getCity_list().size(); c++){//遍历该省份的所有城市
                String CityName = jsonBean.get(i).getCity_list().get(c);
                CityList.add(CityName);//添加城市

            }

            /**
             * 添加城市数据
             */
            options2Items.add(CityList);
        }

        mHandler.sendEmptyMessage(MSG_LOAD_SUCCESS);

    }

    public ArrayList<CityBean> parseData(String result) {//Gson 解析
        ArrayList<CityBean> 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": [
      "乌鲁木齐",
      "伊犁",
      "克孜勒苏",
      "克拉玛依",
      "区直辖",
      "博尔塔拉",
      "吐鲁番",
      "和田",
      "哈密",
      "喀什",
      "塔城",
      "巴音郭楞",
      "昌吉",
      "阿克苏",
      "阿勒泰"
    ]
  }
]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,612评论 4 59
  • 第三天,结束。
    米修a米修阅读 88评论 0 0
  • 基本思路: 1. 用最多K个元素的最大堆max_heap记录最终结果 2. 最大堆的max_heap的所有叶子节点...
    程序员大雄阅读 2,506评论 0 50