PickerView控件的作者在3.0版本中对PickerView源码进行了重构。重构后的PickerView添加了很多可自定义的属性,比如可以自定义文字颜色、大小等。使用也更加方便了。只是改动较大,使用方法也与2.0版本有不少差别。
由于2.0版本时候作者没有给出详细的省市区三级联动的Demo。因此才有了这篇文章。现在3.0版本作者已经给出了很详细的例子。大家可以到作者的github下载Demo作参考:
PickerView项目地址:https://github.com/saiwu-bigkoo/Android-PickerView
最近在做项目时有一个选择省市区的三级联动效果。百度上搜了好久也没找到一个合适的控件。后来再github上找到一个不错的三级联动控件,拿来用发现效果还挺好。把自己写的一个demo分享一下。
控件名称为PickerView,实现了 iOS 的 PickerView 的效果,并且有时间选择和选项选择还支持一二三级联动效果。
PickerView项目地址:https://github.com/saiwu-bigkoo/Android-PickerView
控件用起来非常简单,但在填充数据时稍微有些麻烦,我这里用的省市区数据为json格式,json数据就不贴出了,稍后会把源码上传。
先看下效果图:
首先使用gradle 依赖
compile 'com.bigkoo:pickerview:2.1.0'
布局文件只有一个TextView
省份的实体类(控件的数据格式要求须有一个省份实体类)
public class ProvinceBean {
private String name;
public ProvinceBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/*这个用来显示在PickerView上面的字符串,PickerView会通过反射获
取getPickerViewText方法显示出来。*/
public String getPickerViewText() {
//这里还可以判断文字超长截断再提供显示
return this.name;
}
}
下面这个类用来读取json数据,并将读取到的数据以String格式返回(json数据放在assets目录下,文件名为province_data.json)
// 读取assets中的json文件
public class JsonFileReader {
public static String getJson(Context context, String fileName) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open(fileName);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
byte[] buffer = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return baos.toString();
}
}
MainActivity中的代码,注释写的非常详细,这里就不作太多解释了,详情看代码。
public class MainActivity extends AppCompatActivity {
private TextView mTextViewAddress;
OptionsPickerView pvOptions;
// 省份
ArrayList provinceBeanList = new ArrayList<>();
// 城市
ArrayList cities;
ArrayList> cityList = new ArrayList<>();
// 区/县
ArrayList district;
ArrayList> districts;
ArrayList>> districtList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建选项选择器
pvOptions = new OptionsPickerView(this);
mTextViewAddress = (TextView) findViewById(R.id.tv_address);
// 获取json数据
String province_data_json = JsonFileReader.getJson(this, "province_data.json");
// 解析json数据
parseJson(province_data_json);
// 设置三级联动效果
pvOptions.setPicker(provinceBeanList, cityList, districtList, true);
// 设置选择的三级单位
//pvOptions.setLabels("省", "市", "区");
//pvOptions.setTitle("选择城市");
// 设置是否循环滚动
pvOptions.setCyclic(false, false, false);
// 设置默认选中的三级项目
pvOptions.setSelectOptions(0, 0, 0);
// 监听确定选择按钮
pvOptions.setOnoptionsSelectListener(new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3) {
//返回的分别是三个级别的选中位置
String city = provinceBeanList.get(options1).getPickerViewText();
String address;
// 如果是直辖市或者特别行政区只设置市和区/县
if ("北京市".equals(city) || "上海市".equals(city) || "天津市".equals(city) || "重庆市".equals(city) || "澳门".equals(city) || "香港".equals(city)) {
address = provinceBeanList.get(options1).getPickerViewText()
+ " " + districtList.get(options1).get(option2).get(options3);
} else {
address = provinceBeanList.get(options1).getPickerViewText()
+ " " + cityList.get(options1).get(option2)
+ " " + districtList.get(options1).get(option2).get(options3);
}
mTextViewAddress.setText(address);
}
});
// 点击弹出选项选择器
mTextViewAddress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvOptions.show();
}
});
}
// 解析json填充集合
public void parseJson(String str) {
try {
// 获取json中的数组
JSONArray jsonArray = new JSONArray(str);
// 遍历数据组
for (int i = 0; i < jsonArray.length(); i++) {
// 获取省份的对象
JSONObject provinceObject = jsonArray.optJSONObject(i);
// 获取省份名称放入集合
String provinceName = provinceObject.getString("name");
provinceBeanList.add(new ProvinceBean(provinceName));
// 获取城市数组
JSONArray cityArray = provinceObject.optJSONArray("city");
cities = new ArrayList<>();// 声明存放城市的集合
districts = new ArrayList<>();//声明存放区县集合的集合
// 遍历城市数组
for (int j = 0; j < cityArray.length(); j++) {
// 获取城市对象
JSONObject cityObject = cityArray.optJSONObject(j);
// 将城市放入集合
String cityName = cityObject.optString("name");
cities.add(cityName);
district = new ArrayList<>();// 声明存放区县的集合
// 获取区县的数组
JSONArray areaArray = cityObject.optJSONArray("area");
// 遍历区县数组,获取到区县名称并放入集合
for (int k = 0; k < areaArray.length(); k++) {
String areaName = areaArray.getString(k);
district.add(areaName);
}
// 将区县的集合放入集合
districts.add(district);
}
// 将存放区县集合的集合放入集合
districtList.add(districts);
// 将存放城市的集合放入集合
cityList.add(cities);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
就这么简单一个三级联动效果就实现了。
修改字体大小及颜色可以参看这篇文章:Android-PickerView 三级联动选择器的标题和内容的字体大小、颜色设置
给大家推荐一下BannerViewPager。这是一个基于ViewPager实现的具有强大功能的无限轮播库。通过BannerViewPager可以实现腾讯视频、QQ音乐、酷狗音乐、支付宝、天猫、淘宝、优酷视频、喜马拉雅、网易云音乐、哔哩哔哩等APP的Banner样式以及指示器样式。
欢迎大家到github关注BannerViewPager!