Android 选择器 PickerView实例,时间选择器、地址选择器、单项选择器、多项选择器自定义布局
程序员文章站
2023-01-21 22:28:26
是采用的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是在解析地址文件的时...
是采用的github开源库PickerView,省时省力。最终效果图见最后
首先添加依赖:
//PickerView 选择器
implementation 'com.contrarywind:Android-PickerView:4.1.9'
//谷歌Gson
implementation 'com.google.code.gson:gson:2.8.6'
//eventbus
implementation '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.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="280dp"
android:background="@drawable/shape_picker_bg">
<TextView
android: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" />
<TextView
android: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" />
<LinearLayout
android: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.WheelView
android:id="@+id/options1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.contrarywind.view.WheelView
android:id="@+id/options2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.contrarywind.view.WheelView
android: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() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
//
}
})
.setLayoutRes(R.layout.picker_location, new CustomListener() {
@Override
public 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() {
@Override
public 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() {
@Override
public 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.csdn.net/download/qq_37980878/12582869
本文地址:https://blog.csdn.net/qq_37980878/article/details/107169866
上一篇: 清淡的菜肴,了解一下