最好用的Android省市区三级联动选择效果

所属分类: 软件编程 / Android 阅读数: 36
收藏 0 赞 0 分享

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,即可拿到结果。

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

代码地址:下载地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Android中加入名片扫描功能实例代码

这篇文章主要介绍了Android中加入名片扫描功能实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android仿微信发表说说实现拍照、多图上传功能

这篇文章主要为大家详细介绍了Android仿微信发表说说实现拍照、多图上传功能,使用Retrofit2.0技术,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

设置Android系统永不锁屏永不休眠的方法

在进行Android系统开发的时候,有些特定的情况需要设置系统永不锁屏,永不休眠。本篇文章给大家介绍Android 永不锁屏,开机不锁屏,删除设置中休眠时间选项,需要的朋友一起学习吧
收藏 0 赞 0 分享

Android Retrofit 2.0框架上传图片解决方案

这篇文章主要介绍了Android Retrofit 2.0框架上传一张与多张图片解决方案,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android自定义等待对话框

这篇文章主要为大家详细介绍了Android自定义等待对话框的实现方法,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Android中Window添加View的底层原理

这篇文章主要介绍了Android中Window添加View的底层原理,需要的朋友可以参考下
收藏 0 赞 0 分享

Android调用系统默认浏览器访问的方法

这篇文章主要介绍了Android调用系统默认浏览器访问的方法的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Android开发退出程序的方法汇总

Android程序有很多Activity,比如说主窗口A,调用了子窗口B,子窗口B又调用子窗口C,back返回子窗口B后,在B中如何关闭整个Android应用程序呢? 下面脚本之家小编就给大家介绍android开发退出程序的几种方法,感兴趣的朋友参考下吧
收藏 0 赞 0 分享

Android程序开发中单选按钮(RadioGroup)的使用详解

在android程序开发中,无论是单选按钮还是多选按钮都非常的常见,接下来通过本文给大家介绍Android程序开发中单选按钮(RadioGroup)的使用,需要的朋友参考下吧
收藏 0 赞 0 分享

Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中

这篇文章主要介绍了Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多