是采用的github开源库PickerView,省时省力。最终效果图见最后
首先添加依赖:
//PickerView 选择器implementation 'com.contrarywind:Android-PickerView:4.1.9'//谷歌Gsonimplementation 'com.google.code.gson:gson:2.8.6'//eventbusimplementation 'org.greenrobot:eventbus:3.2.0'
Gson是在解析地址文件的时候要用,eventbus是传递选择的数据的时候要用。
因为他给的布局通常是不太符合你实际需求的,所以使用自定义布局的方式,先去写好自己的布局文件,如地址的
picker_location.xml
因为有多个地方要重用选择器的部分,所以我使用include方便重用:
include_picker_bg.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"android:layout_width="match_parent"android:layout_height="280dp"android:background="@drawable/shape_picker_bg"><TextViewandroid:id="@+id/include_picker_tv_cancle"android:layout_width="30dp"android:layout_height="30dp"android:text="取消"android:textSize="14dp"android:layout_marginLeft="20dp"android:layout_marginTop="20dp"android:textColor="@color/black_1A"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/include_picker_tv_submit"android:layout_width="30dp"android:layout_height="30dp"android:text="确定"android:textSize="14dp"android:layout_marginRight="20dp"android:layout_marginTop="20dp"android:textColor="@color/gray_9A"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><LinearLayoutandroid:id="@+id/optionspicker"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="150dp"android:gravity="center"android:background="@android:color/white"android:orientation="horizontal"android:layout_marginTop="20dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"><com.contrarywind.view.WheelViewandroid:id="@+id/options1"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><com.contrarywind.view.WheelViewandroid:id="@+id/options2"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><com.contrarywind.view.WheelViewandroid:id="@+id/options3"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>
我将这几个封装成了一个工具类,其中显示地址的代码:
private OptionsPickerView locationOptions;//显示地址选择器public void showLocationPicker() {// 弹出选择器if(!isLoaded){Toast.makeText(context,context.getResources().getString(R.string.loading_location_data),Toast.LENGTH_SHORT).show();return;}locationOptions = new OptionsPickerBuilder(context, new OnOptionsSelectListener() {@Overridepublic void onOptionsSelect(int options1, int options2, int options3, View v) {//}}).setLayoutRes(R.layout.picker_location, new CustomListener() {@Overridepublic void customLayout(View v) {final TextView tvSubmit = v.findViewById(R.id.picker_location_inc_bg).findViewById(R.id.include_picker_tv_submit);final TextView tvCancle = v.findViewById(R.id.picker_location_inc_bg).findViewById(R.id.include_picker_tv_cancle);tvSubmit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(!isChanged){//没有改变默认选择第一项String firstLocation = options1Items.get(0).getPickerViewText() + "\t" + options2Items.get(0).get(0);EventBus.getDefault().post(new PickerMessageEvent(MESSAGE_TYPE_LOCATION,firstLocation,"0"));}else {EventBus.getDefault().post(new PickerMessageEvent(MESSAGE_TYPE_LOCATION,checkedLocation,"0"));}locationOptions.dismiss();}});}}).setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() {@Overridepublic void onOptionsSelectChanged(int options1, int options2, int options3) {String opt1tx = options1Items.size() > 0 ?options1Items.get(options1).getPickerViewText() : "";String opt2tx = options2Items.size() > 0&& options2Items.get(options1).size() > 0 ?options2Items.get(options1).get(options2) : "";checkedLocation = opt1tx + "\t" + opt2tx;isChanged = true;}}).setLineSpacingMultiplier(2.4f)//设置距离.setItemVisibleCount(3)//设置显示的数据数量.setContentTextSize(17)//设置标题字号.isRestoreItem(true)//是否每次从头开始显示数据.isAlphaGradient(true).build();locationOptions.setPicker(options1Items, options2Items);locationOptions.show();}//初始化地区数据private void initJsonData() {//解析数据/*** 注意:assets 目录下的Json文件仅供参考,实际使用可自行替换文件* 关键逻辑在于循环体** */String JsonData = new GetJsonDataUtil().getJson(context, "province.json");//获取assets目录下的json文件数据ArrayList<JsonBean> jsonBean = parseData(JsonData);//用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).getCityList().size(); c++) {//遍历该省份的所有城市String cityName = jsonBean.get(i).getCityList().get(c).getName();cityList.add(cityName);//添加城市//ArrayList<String> city_AreaList = new ArrayList<>();//该城市的所有地区列表//如果无地区数据,建议添加空字符串,防止数据为null 导致三个选项长度不匹配造成崩溃/*if (jsonBean.get(i).getCityList().get(c).getArea() == null|| jsonBean.get(i).getCityList().get(c).getArea().size() == 0) {city_AreaList.add("");} else {city_AreaList.addAll(jsonBean.get(i).getCityList().get(c).getArea());}*///city_AreaList.addAll(jsonBean.get(i).getCityList().get(c).getArea());//province_AreaList.add(city_AreaList);//添加该省所有地区数据}/*** 添加城市数据*/options2Items.add(cityList);/*** 添加地区数据*/// options3Items.add(province_AreaList);}mHandler.sendEmptyMessage(MSG_LOAD_SUCCESS);}//解析地区json文件public ArrayList<JsonBean> parseData(String result) {//Gson 解析ArrayList<JsonBean> detail = new ArrayList<>();try {JSONArray data = new JSONArray(result);Gson gson = new Gson();for (int i = 0; i < data.length(); i++) {JsonBean entity = gson.fromJson(data.optJSONObject(i).toString(), JsonBean.class);detail.add(entity);}} catch (Exception e) {e.printStackTrace();mHandler.sendEmptyMessage(MSG_LOAD_FAILED);}return detail;}public void removeHandler(){if (mHandler != null) {mHandler.removeCallbacksAndMessages(null);}}
其中
String JsonData = new GetJsonDataUtil().getJson(context, "province.json");//获取assets目录下的json文件数据
是一份地址数据文件放在本地assets。
JsonBean和GetJsonDataUtil请参照源码,不过多解释。
最后效果:
自己需要什么样的效果就通过布局文件和locationOptions.set...去设置
源码:///download/qq_37980878/12582869