仿ios滚动日期控件,所有的三级联动都在这里
从上个月15号来到吉林出差,几乎就没有正常下过班,虽说每天没干到凌晨一两点,但基本也都是10点以后回去。既然选择了这工作,那也得认命,现在所有的努力都是为了以后更好的生活。再说习大大不也说了嘛,“2017年,撸起袖子,加油干”。年轻,你就得可劲造。
配一张我女朋友的照片不好意思,前面我装了个13,各位看官老爷别骂我。下面进入正题,今天在业务测试时,他们提出一个需求,把现有的系统自带的选择日期控件,改成像ios那样可以滚动的。虽然听到这个消息,心里是不高兴的,但是想着也不是啥大事,就自己摸索下吧、
安卓原生日期控件- 在github上找到了一个叫TimePickerView的开源框架,有时间选择和选项选择,并支持一二三级联动,支持自定义样式,新版本的详细特性如下:
1、有时间和选项这两种选择器
2、选项选择器支持三级联动
3、时间选择器支持起始和终止日期设定
4、支持“年,月,日,时,分,秒”,“省,市,区”等选项的单位(label)显示、隐藏和自定义
5、支持自定义文字、颜色、文字大小等属性
6、支持背景颜色更换,有夜间模式需求的问题可以解决了
7、Item的文字长度过长时,文字会自适应缩放到Item的长度,避免显示不完全的问题
——TimePickerView 时间选择器,支持年月日时分,年月日,年月,时分等格式
——OptionsPickerView 选项选择器,支持一,二,三级选项选择,并且可以设置是否联动
先上效果图:
时间选择器.gif 选项选择器.gif 自定义时间选择器 自定义选项选择器.gif 不联动时间选择器.gif 三级联动省市区.gif使用步骤:
1、在Jcenter仓库添加 Gradle依赖:
compile 'com.contrarywind:Android-PickerView:3.2.4'
2.在Activity中添加如下代码就可以使用了:
//时间选择器
TimePickerView pvTime = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date,View v) {//选中事件回调
Toast.makeText(Main2Activity.this,getTime(date),Toast.LENGTH_LONG).show();
}
})
.build();
pvTime.setDate(Calendar.getInstance());//注:根据需求来决定是否使用该方法(一般是精确到秒的情况),此项可以在弹出选择器的时候重新设置当前时间,避免在初始化之后由于时间已经设定,导致选中时间与当前时间不匹配的问题。
pvTime.show();//显示时间选择器
3.如果默认样式不符合你的口味,也可以自定义各种属性:
Calendar selectedDate = Calendar.getInstance();
Calendar startDate = Calendar.getInstance();
startDate.set(2013,1,1);
Calendar endDate = Calendar.getInstance();
endDate.set(2020,1,1);
pvTime = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date,View v) {//选中事件回调
tvTime.setText(getTime(date));
}
})
.setType(TimePickerView.Type.ALL)//默认全部显示
.setCancelText("Cancel")//取消按钮文字
.setSubmitText("Sure")//确认按钮文字
.setContentSize(18)//滚轮文字大小
.setTitleSize(20)//标题文字大小
.setTitleText("Title")//标题文字
.setOutSideCancelable(false)//点击屏幕,点在控件外部范围时,是否取消显示
.isCyclic(true)//是否循环滚动
.setTitleColor(Color.BLACK)//标题文字颜色
.setSubmitColor(Color.BLUE)//确定按钮文字颜色
.setCancelColor(Color.BLUE)//取消按钮文字颜色
.setTitleBgColor(0xFF666666)//标题背景颜色 Night mode
.setBgColor(0xFF333333)//滚轮背景颜色 Night mode
.setRange(calendar.get(Calendar.YEAR) - 20, calendar.get(Calendar.YEAR) + 20)//默认是1900-2100年
.setDate(selectedDate)// 如果不设置的话,默认是系统时间*/
.setRangDate(startDate,endDate)//起始终止年月日设定
.setLabel("年","月","日","时","分","秒")
.isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。
.isDialog(true)//是否显示为对话框样式
.build();
4.如果需要自定义布局:
// 注意:自定义布局中,id为 optionspicker 或者 timepicker 的布局以及其子控件必须要有,否则会报空指针
// 具体可参考demo 里面的两个自定义布局
pvCustomOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3, View v) {
//返回的分别是三个级别的选中位置
String tx = cardItem.get(options1).getPickerViewText();
btn_CustomOptions.setText(tx);
}
})
.setLayoutRes(R.layout.pickerview_custom_options, new CustomListener() {
@Override
public void customLayout(View v) {
//自定义布局中的控件初始化及事件处理
final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish);
final TextView tvAdd = (TextView) v.findViewById(R.id.tv_add);
ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel);
tvSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomOptions.returnData(tvSubmit);
}
});
ivCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomOptions.dismiss();
}
});
tvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData();
pvCustomOptions.setPicker(cardItem);
}
});
}
})
.build();
pvCustomOptions.setPicker(cardItem);//添加数据
5.对使用还有疑问的话,请参考下面代码(代码量大,注释也很清晰,使用起来很方便)
Main2Activity代码
package com.e_valmont.look_lookdemo;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bigkoo.pickerview.OptionsPickerView;
import com.bigkoo.pickerview.TimePickerView;
import com.bigkoo.pickerview.listener.CustomListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
/**
* 主页面
*/
public class Main2Activity extends AppCompatActivity implements View.OnClickListener{
/*按钮*/
private Button btn_Time;//时间选择器
private Button btn_Options;//选项选择器
private Button btn_CustomOptions;
private Button btn_CustomTime;
private Button btn_no_linkage;//无联动选择器
private Button btn_goToJsonData;//解析json数据
/*选择器*/
private TimePickerView pvTime;
private TimePickerView pvCustomTime;
private OptionsPickerView pvOptions;
private OptionsPickerView pvCustomOptions;
private OptionsPickerView pvNoLinkOptions;
private ArrayList<CardBean> cardItem = new ArrayList<>();
/*无联动数据*/
private ArrayList<String> food = new ArrayList<>();//食品类型
private ArrayList<String> clothes = new ArrayList<>();//衣服品牌
private ArrayList<String> computer = new ArrayList<>();//电脑品牌
private ArrayList<ProvinceBean> options1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
//最好等数据加载完毕再初始化并显示,以免数据量大的时候,还未加载完毕就显示,造成APP崩溃。
initTimePicker();
initCustomTimePicker();
initOptionData();
initOptionPicker();
initCustomOptionPicker();
initNoLinkOptionsPicker();
initClilck();
}
private void initView(){
btn_Time = (Button) findViewById(R.id.btn_Time);
btn_Options = (Button) findViewById(R.id.btn_Options);
btn_CustomOptions = (Button) findViewById(R.id.btn_CustomOptions);
btn_CustomTime = (Button) findViewById(R.id.btn_CustomTime);
btn_no_linkage = (Button) findViewById(R.id.btn_no_linkage);
btn_goToJsonData = (Button) findViewById(R.id.btn_GotoJsonData);
}
private void initClilck(){
btn_Time.setOnClickListener(this);
btn_Options.setOnClickListener(this);
btn_CustomOptions.setOnClickListener(this);
btn_CustomTime.setOnClickListener(this);
btn_no_linkage.setOnClickListener(this);
btn_goToJsonData.setOnClickListener(this);
}
/**
* 初始化时间选择器
**/
private void initTimePicker() {
//控制时间范围(如果不设置范围,默认时间1900-2100年)
//因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11
Calendar selectedDate = Calendar.getInstance();
Calendar startDate = Calendar.getInstance();
startDate.set(1900,1,1);
Calendar endDate = Calendar.getInstance();
endDate.set(2100,12,31);
//时间选择器
pvTime = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {//选中事件回调
// 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null
// //点击确定时,按钮显示选中时间
// Button btn = (Button) v;
// btn.setText(getTime(date));
Toast.makeText(Main2Activity.this,getTime(date),Toast.LENGTH_LONG).show();
}
})
.setType(TimePickerView.Type.YEAR_MONTH_DAY)//显示样式,共6种
.setLabel("", "", "", "", "", "") //设置空字符串以隐藏单位提示,可任意选填其中几个或不填,eg:年月日时分秒
.setDividerColor(Color.TRANSPARENT)//分隔线颜色
.setContentSize(20)//字体大小
.isCyclic(true)//设置是否循环
.setDate(selectedDate)
.setRangDate(startDate,endDate)
.build();
}
/**
* 初始化自定义时间选择器
* */
private void initCustomTimePicker() {
/**
* @description
*
* 注意事项:
* 1.自定义布局中,id为 optionspicker 或者 timepicker 的布局以及其子控件必须要有,否则会报空指针.
* 具体可参考demo 里面的两个自定义layout布局。
* 2.因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11
* setRangDate方法控制起始终止时间(如果不设置范围,则使用默认时间1900-2100年,此段代码可注释)
*/
Calendar selectedDate = Calendar.getInstance();//系统当前时间
Calendar startDate = Calendar.getInstance();
startDate.set(2014,1,23);
Calendar endDate = Calendar.getInstance();
endDate.set(2027,0,28);//月份0-11代表1-12
//时间选择器 ,自定义布局
pvCustomTime = new TimePickerView.Builder(this, new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {//选中事件回调
//btn_CustomTime.setText(getTime(date));
Toast.makeText(Main2Activity.this,getTime(date),Toast.LENGTH_LONG).show();
}
})
/*.setType(TimePickerView.Type.ALL)//default is all
.setCancelText("Cancel")
.setSubmitText("Sure")
.setContentSize(18)
.setTitleSize(20)
.setTitleText("Title")
.setTitleColor(Color.BLACK)
/*.setDividerColor(Color.WHITE)//设置分割线的颜色
.setTextColorCenter(Color.LTGRAY)//设置选中项的颜色
.setLineSpacingMultiplier(1.6f)//设置两横线之间的间隔倍数
.setTitleBgColor(Color.DKGRAY)//标题背景颜色 Night mode
.setBgColor(Color.BLACK)//滚轮背景颜色 Night mode
.setSubmitColor(Color.WHITE)
.setCancelColor(Color.WHITE)*/
/*.gravity(Gravity.RIGHT)// default is center*/
.setDate(selectedDate)
.setRangDate(startDate,endDate)
.setLayoutRes(R.layout.pickerview_custom_time, new CustomListener() {
@Override
public void customLayout(View v) {
final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish);
ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel);
tvSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomTime.returnData();
}
});
ivCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomTime.dismiss();
}
});
}
})
.setType(TimePickerView.Type.YEAR_MONTH_DAY)
.isCenterLabel(true) //是否只显示中间选中项的label文字,false则每项item全部都带有label。
.setDividerColor(Color.RED)
.isCyclic(true)
.build();
}
/**
* 初始化无联动选项选择器
* */
private void initNoLinkOptionsPicker() {
pvNoLinkOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
String str = "食品:"+food.get(options1)
+"\n衣服:"+clothes.get(options2)
+"\n电脑:"+computer.get(options3);
Toast.makeText(Main2Activity.this,str,Toast.LENGTH_SHORT).show();
}
})
.build();
pvNoLinkOptions.setNPicker(food,clothes,computer);//设置数据
}
/**
* 初始化选择器数据
* */
private void initOptionData() {
/**
* 注意:如果是添加JavaBean实体数据,则实体类需要实现 IPickerViewData 接口,
* PickerView会通过getPickerViewText方法获取字符串显示出来。
*/
getCardData();
getNoLinkData();
//选项1
options1Items.add(new ProvinceBean(0,"广东","描述部分","其他数据"));
options1Items.add(new ProvinceBean(1,"湖南","描述部分","其他数据"));
options1Items.add(new ProvinceBean(2,"广西","描述部分","其他数据"));
//选项2
ArrayList<String> options2Items_01 = new ArrayList<>();
options2Items_01.add("广州");
options2Items_01.add("佛山");
options2Items_01.add("东莞");
options2Items_01.add("珠海");
ArrayList<String> options2Items_02 = new ArrayList<>();
options2Items_02.add("长沙");
options2Items_02.add("岳阳");
options2Items_02.add("株洲");
options2Items_02.add("衡阳");
ArrayList<String> options2Items_03 = new ArrayList<>();
options2Items_03.add("桂林");
options2Items_03.add("玉林");
options2Items.add(options2Items_01);
options2Items.add(options2Items_02);
options2Items.add(options2Items_03);
/*--------数据源添加完毕---------*/
}
/**
* 初始化条件选择器
* */
private void initOptionPicker() {
/**
* 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。
*/
pvOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
//返回的分别是三个级别的选中位置
String tx = options1Items.get(options1).getPickerViewText()
+ options2Items.get(options1).get(options2)
/* + options3Items.get(options1).get(options2).get(options3).getPickerViewText()*/;
// btn_Options.setText(tx);
Toast.makeText(Main2Activity.this,tx,Toast.LENGTH_SHORT).show();
}
})
.setTitleText("城市选择")
.setContentTextSize(20)//设置滚轮文字大小
.setDividerColor(Color.GREEN)//设置分割线的颜色
.setSelectOptions(0,1)//默认选中项
.setBgColor(Color.BLACK)
.setTitleBgColor(Color.DKGRAY)
.setTitleColor(Color.LTGRAY)
.setCancelColor(Color.YELLOW)
.setSubmitColor(Color.YELLOW)
.setTextColorCenter(Color.LTGRAY)
.isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。
.setLabels("省","市","区")
.build();
//pvOptions.setSelectOptions(1,1);
/*pvOptions.setPicker(options1Items);//一级选择器*/
pvOptions.setPicker(options1Items, options2Items);//二级选择器
/*pvOptions.setPicker(options1Items, options2Items,options3Items);//三级选择器*/
}
/**
* 初始化自定义选项选择器
* */
private void initCustomOptionPicker() {//条件选择器初始化,自定义布局
/**
* @description
*
* 注意事项:
* 自定义布局中,id为 optionspicker 或者 timepicker 的布局以及其子控件必须要有,否则会报空指针。
* 具体可参考demo 里面的两个自定义layout布局。
*/
pvCustomOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3, View v) {
//返回的分别是三个级别的选中位置
String tx = cardItem.get(options1).getPickerViewText();
// btn_CustomOptions.setText(tx);
Toast.makeText(Main2Activity.this,tx,Toast.LENGTH_SHORT).show();
}
})
.setLayoutRes(R.layout.pickerview_custom_options, new CustomListener() {
@Override
public void customLayout(View v) {
final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish);
final TextView tvAdd = (TextView) v.findViewById(R.id.tv_add);
ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel);
tvSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomOptions.returnData();
}
});
ivCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomOptions.dismiss();
}
});
tvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getCardData();
pvCustomOptions.setPicker(cardItem);
}
});
}
})
.isDialog(true)
.build();
pvCustomOptions.setPicker(cardItem);//添加数据
}
/**
* 添加油卡信息
* */
private void getCardData() {
for (int i = 0; i < 5; i++) {
cardItem.add(new CardBean(i, "No.ABC12345 " + i));
}
}
/**
* 添加无联动数据
* */
private void getNoLinkData() {
food.add("肯德基");
food.add("麦当劳");
food.add("披萨");
clothes.add("耐克");
clothes.add("阿迪");
clothes.add("匡威");
computer.add("华硕");
computer.add("联想");
computer.add("苹果");
computer.add("惠普");
}
/**
* @describe 时间显示样式
* @params Date
* @return 时间
**/
private String getTime(Date date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//时间显示样式,可选
return format.format(date);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_Time && pvTime != null) {
// pvTime.setDate(Calendar.getInstance());
/* pvTime.show(); //show timePicker*/
pvTime.show(v);//弹出时间选择器,传递参数过去,回调的时候则可以绑定此view
} else if (v.getId() == R.id.btn_Options && pvOptions != null) {
pvOptions.show(); //弹出条件选择器
} else if (v.getId() == R.id.btn_CustomOptions && pvCustomOptions != null) {
pvCustomOptions.show(); //弹出自定义条件选择器
}else if (v.getId() == R.id.btn_CustomTime && pvCustomTime != null) {
pvCustomTime.show(); //弹出自定义时间选择器
}else if (v.getId() == R.id.btn_no_linkage&& pvNoLinkOptions !=null){//不联动数据选择器
pvNoLinkOptions.show();
}else if (v.getId() == R.id.btn_GotoJsonData){//跳转到 省市区解析示例页面
startActivity(new Intent(Main2Activity.this,JsonDataActivity.class));
}
}
}
JsonDataActivity 代码
package com.e_valmont.look_lookdemo;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import com.bigkoo.pickerview.OptionsPickerView;
import com.google.gson.Gson;
import org.json.JSONArray;
import java.util.ArrayList;
/***
* 解析Json文件,并三级联动显示
*/
public class JsonDataActivity extends AppCompatActivity implements View.OnClickListener{
/*省市区数据集合*/
private ArrayList<JsonBean> options1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
private ArrayList<ArrayList<ArrayList<String>>> options3Items = 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;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_json_data);
initView();
}
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LOAD_DATA:
if (thread==null){//如果已创建就不再重新创建子线程了
Toast.makeText(JsonDataActivity.this,"开始解析数据",Toast.LENGTH_SHORT).show();
thread = new Thread(new Runnable() {
@Override
public void run() {
// 写子线程中的操作,解析省市区数据
initJsonData();
}
});
thread.start();
}
break;
case MSG_LOAD_SUCCESS:
Toast.makeText(JsonDataActivity.this,"解析数据成功",Toast.LENGTH_SHORT).show();
isLoaded = true;
break;
case MSG_LOAD_FAILED:
Toast.makeText(JsonDataActivity.this,"解析数据失败",Toast.LENGTH_SHORT).show();
break;
}
}
};
private void initView() {
findViewById(R.id.btn_data).setOnClickListener(this);
findViewById(R.id.btn_show).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_data:
mHandler.sendEmptyMessage(MSG_LOAD_DATA);
break;
case R.id.btn_show:
if (isLoaded){
ShowPickerView();
}else {
Toast.makeText(JsonDataActivity.this,"数据暂未解析成功,请等待",Toast.LENGTH_SHORT).show();
}
break;
}
}
/**
* 弹出选择器
* */
private void ShowPickerView() {
OptionsPickerView pvOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
//返回的分别是三个级别的选中位置
String tx = options1Items.get(options1).getPickerViewText()+
options2Items.get(options1).get(options2)+
options3Items.get(options1).get(options2).get(options3);
Toast.makeText(JsonDataActivity.this,tx,Toast.LENGTH_SHORT).show();
}
})
.setTitleText("城市选择")
.setDividerColor(Color.BLACK)
.setTextColorCenter(Color.BLACK) //设置选中项文字颜色
.setContentTextSize(20)
.setOutSideCancelable(false)// default is true
.build();
/*pvOptions.setPicker(options1Items);//一级选择器
pvOptions.setPicker(options1Items, options2Items);//二级选择器*/
pvOptions.setPicker(options1Items, options2Items,options3Items);//三级选择器
pvOptions.show();
}
/**
* 解析数据
* */
private void initJsonData() {
/**
* 注意:assets 目录下的Json文件仅供参考,实际使用可自行替换文件
* 关键逻辑在于循环体
* */
String JsonData = new GetJsonDataUtil().getJson(this,"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 {
for (int d=0; d < jsonBean.get(i).getCityList().get(c).getArea().size(); d++) {//该城市对应地区所有数据
String AreaName = jsonBean.get(i).getCityList().get(c).getArea().get(d);
City_AreaList.add(AreaName);//添加该城市所有地区数据
}
}
Province_AreaList.add(City_AreaList);//添加该省所有地区数据
}
/**
* 添加城市数据
*/
options2Items.add(CityList);
/**
* 添加地区数据
*/
options3Items.add(Province_AreaList);
}
mHandler.sendEmptyMessage(MSG_LOAD_SUCCESS);
}
/**
* Gson 解析
* */
public ArrayList<JsonBean> parseData(String result) {
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;
}
}
CardBean 实体类代码
package com.e_valmont.look_lookdemo;
import com.bigkoo.pickerview.model.IPickerViewData;
/**
* 油卡实体类
*/
public class CardBean implements IPickerViewData {
int id;
String cardNo;
public CardBean(int id, String cardNo) {
this.id = id;
this.cardNo = cardNo;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
@Override
public String getPickerViewText() {
return cardNo;
}
}
ProvinceBean 实体类代码
package com.e_valmont.look_lookdemo;
import com.bigkoo.pickerview.model.IPickerViewData;
/**
* 省份实体类
*/
public class ProvinceBean implements IPickerViewData {
private long id;
private String name;
private String description;
private String others;
public ProvinceBean(long id,String name,String description,String others){
this.id = id;
this.name = name;
this.description = description;
this.others = others;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getOthers() {
return others;
}
public void setOthers(String others) {
this.others = others;
}
//这个用来显示在PickerView上面的字符串,PickerView会通过getPickerViewText方法获取字符串显示出来。
@Override
public String getPickerViewText() {
return name;
}
}
JsonBean 实体类代码
package com.e_valmont.look_lookdemo;
import com.bigkoo.pickerview.model.IPickerViewData;
import java.util.List;
/**
* 省市区实体类
*/
public class JsonBean implements IPickerViewData {
/**
* name : 省份
* city : [{"name":"北京市","area":["东城区","西城区","崇文区","宣武区","朝阳区"]}]
*/
private String name;
private List<CityBean> city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CityBean> getCityList() {
return city;
}
public void setCityList(List<CityBean> city) {
this.city = city;
}
// 实现 IPickerViewData 接口,
// 这个用来显示在PickerView上面的字符串,
// PickerView会通过IPickerViewData获取getPickerViewText方法显示出来。
@Override
public String getPickerViewText() {
return this.name;
}
public static class CityBean {
/**
* name : 城市
* area : ["东城区","西城区","崇文区","昌平区"]
*/
private String name;
private List<String> area;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getArea() {
return area;
}
public void setArea(List<String> area) {
this.area = area;
}
}
}
GetJsonDataUtil 工具类
package com.e_valmont.look_lookdemo;
import android.content.Context;
import android.content.res.AssetManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 解析本地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();
}
}
activity_main2.xml布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_Time"
android:layout_margin="10dp"
android:text="时间选择器"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<Button
android:id="@+id/btn_Options"
android:layout_margin="10dp"
android:layout_below="@+id/tvTime"
android:text="选项选择器"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<Button
android:id="@+id/btn_CustomTime"
android:layout_margin="10dp"
android:layout_below="@+id/tvTime"
android:text="自定义时间选择器"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<Button
android:id="@+id/btn_CustomOptions"
android:layout_margin="10dp"
android:layout_below="@+id/tvTime"
android:text="自定义选项选择器"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<Button
android:id="@+id/btn_no_linkage"
android:layout_margin="10dp"
android:layout_below="@+id/tvTime"
android:text="条件选择器(不联动)"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<Button
android:id="@+id/btn_GotoJsonData"
android:layout_margin="10dp"
android:layout_below="@+id/tvTime"
android:text="省市区Json文件解析示例"
android:layout_width="match_parent"
android:layout_height="50dp"/>
</LinearLayout>
activity_json_data.xml布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_json_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<Button
android:id="@+id/btn_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解析数据"/>
<Button
android:id="@+id/btn_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="弹出省市区选择器"
android:layout_marginTop="@dimen/activity_horizontal_margin" />
</LinearLayout>
pickerview_custom_time自定义时间选择器布局.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#EEEEEE">
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#aaa" />
<ImageView
android:id="@+id/iv_cancel"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_centerVertical="true"
android:layout_marginLeft="17dp"
android:padding="8dp"
android:src="@drawable/to_down" />
<TextView
android:id="@+id/tv_finish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="17dp"
android:padding="8dp"
android:text="完成"
android:textColor="#24AD9D"
android:textSize="18sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#aaa" />
</RelativeLayout>
<!--此部分需要完整复制过去,删减或者更改ID会导致初始化找不到内容而报空-->
<LinearLayout
android:id="@+id/timepicker"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="horizontal">
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/year"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/month"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/day"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/hour"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/min"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/second"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
</LinearLayout>
</LinearLayout>
pickerview_custom_options.xml自定义选项选择器布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#EEEEEE">
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#aaa" />
<ImageView
android:id="@+id/iv_cancel"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_centerVertical="true"
android:layout_marginLeft="17dp"
android:padding="8dp"
android:src="@drawable/to_down" />
<TextView
android:id="@+id/tv_finish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="17dp"
android:padding="8dp"
android:text="完成"
android:textColor="#24AD9D"
android:textSize="18sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#aaa" />
</RelativeLayout>
<!--此部分需要完整复制过去,删减或者更改ID会导致初始化找不到内容而报空-->
<LinearLayout
android:id="@+id/optionspicker"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="horizontal">
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/options1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/options2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.bigkoo.pickerview.lib.WheelView
android:id="@+id/options3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#24ad9d" />
<TextView
android:id="@+id/tv_add"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#E5E9EC"
android:gravity="center"
android:text="+ 添加加油卡"
android:textColor="#24AD9D"
android:textSize="18sp" />
</LinearLayout>
总结:TimePickerView封装的很灵活,基本可以满足日常开发,滚动日期显示(任意格式)、省市区三级联动、无联动选项选择器等等。代码量大,但是逻辑清晰,各位根据需求使用代码。
参考文章:http://www.jianshu.com/p/d3cab4714b8a 第155条