PickerView--仿ios滾輪時間選擇、城市選擇效果
阿新 • • 發佈:2018-12-16
在專案開發中Android基本都是在跟隨ios的風格,前段時間產品經理就要求按照ios的效果,做時間、城市選擇效果,真要全部自己寫還真有點蛋疼,所以在網上一搜,效果不少,其中PickerView用的人還是蠻多的,所以就決定用PickerView來實現;
PickerView提供了:時間選擇器和選項選擇器
——TimePickerView 時間選擇器,支援年月日時分,年月日,年月,時分等格式。
——OptionsPickerView 選項選擇器,支援一,二,三級選項選擇,並且可以設定是否聯動 。
- 支援三級聯動
- 設定是否聯動
- 設定迴圈模式
- 支援自定義佈局。
- 支援item的分隔線設定。
- 支援item間距設定。
- 時間選擇器支援起始和終止日期設定。
- 支援“年,月,日,時,分,秒”,“省,市,區”等選項的單位(label)顯示、隱藏和自定義。
- 支援自定義文字、顏色、文字大小等屬性
- Item的文字長度過長時,文字會自適應縮放到Item的長度,避免顯示不完全的問題
- 支援Dialog 模式。
- 支援自定義設定容器。
- 實時回撥。
首先先將庫依賴到自己的專案中;
compile 'com.contrarywind:Android-PickerView:4.1.6'
先來看時間選擇器,時間選擇器涉及到TimePickerView和TimePickerBuilder,這裡採用了鏈式程式設計和build設計模式;在TimePickerBuilder中提供了一系列呼叫設定的方法;
public class TimePickerBuilder { private PickerOptions mPickerOptions; //Required public TimePickerBuilder(Context context, OnTimeSelectListener listener) { mPickerOptions = new PickerOptions(PickerOptions.TYPE_PICKER_TIME); mPickerOptions.context = context; mPickerOptions.timeSelectListener = listener; } /** * 設定位置 * @param gravity * @return */ public TimePickerBuilder setGravity(int gravity) { mPickerOptions.textGravity = gravity; return this; } /** * new boolean[]{true, true, true, false, false, false} * control the "year","month","day","hours","minutes","seconds " display or hide. * 分別控制“年”“月”“日”“時”“分”“秒”的顯示或隱藏。 * * @param type 布林型陣列,長度需要設定為6。 * @return TimePickerBuilder */ public TimePickerBuilder setType(boolean[] type) { mPickerOptions.type = type; return this; } /** * 設定提交文字 * @param textContentConfirm * @return */ public TimePickerBuilder setSubmitText(String textContentConfirm) { mPickerOptions.textContentConfirm = textContentConfirm; return this; } /** * 是否是dialog * @param isDialog * @return */ public TimePickerBuilder isDialog(boolean isDialog) { mPickerOptions.isDialog = isDialog; return this; } /** * 設定取消文字 * @param textContentCancel * @return */ public TimePickerBuilder setCancelText(String textContentCancel) { mPickerOptions.textContentCancel = textContentCancel; return this; } /** * 設定標題文字 * @param textContentTitle * @return */ public TimePickerBuilder setTitleText(String textContentTitle) { mPickerOptions.textContentTitle = textContentTitle; return this; } /** * 設定提交文字顏色 * @param textColorConfirm * @return */ public TimePickerBuilder setSubmitColor(int textColorConfirm) { mPickerOptions.textColorConfirm = textColorConfirm; return this; } /** * 設定取消文字顏色 * @param textColorCancel * @return */ public TimePickerBuilder setCancelColor(int textColorCancel) { mPickerOptions.textColorCancel = textColorCancel; return this; } /** * ViewGroup 型別的容器 * * @param decorView 選擇器會被新增到此容器中 * @return TimePickerBuilder */ public TimePickerBuilder setDecorView(ViewGroup decorView) { mPickerOptions.decorView = decorView; return this; } /** * 設定背景顏色 * @param bgColorWheel * @return */ public TimePickerBuilder setBgColor(int bgColorWheel) { mPickerOptions.bgColorWheel = bgColorWheel; return this; } /** * 設定標題背景顏色 * @param bgColorTitle * @return */ public TimePickerBuilder setTitleBgColor(int bgColorTitle) { mPickerOptions.bgColorTitle = bgColorTitle; return this; } /** * 設定標題顏色 * @param textColorTitle * @return */ public TimePickerBuilder setTitleColor(int textColorTitle) { mPickerOptions.textColorTitle = textColorTitle; return this; } public TimePickerBuilder setSubCalSize(int textSizeSubmitCancel) { mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel; return this; } /** * 設定標題文字大小 * @param textSizeTitle * @return */ public TimePickerBuilder setTitleSize(int textSizeTitle) { mPickerOptions.textSizeTitle = textSizeTitle; return this; } /** * 設定當前文字大小 * @param textSizeContent * @return */ public TimePickerBuilder setContentTextSize(int textSizeContent) { mPickerOptions.textSizeContent = textSizeContent; return this; } /** * 因為系統Calendar的月份是從0-11的,所以如果是呼叫Calendar的set方法來設定時間,月份的範圍也要是從0-11 * * @param date * @return TimePickerBuilder */ public TimePickerBuilder setDate(Calendar date) { mPickerOptions.date = date; return this; } /** * 設定自定義佈局 * @param res 資源佈局id * @param customListener 設定自定義佈局回撥 * @return */ public TimePickerBuilder setLayoutRes(int res, CustomListener customListener) { mPickerOptions.layoutRes = res; mPickerOptions.customListener = customListener; return this; } /** * 設定起始時間 * 因為系統Calendar的月份是從0-11的,所以如果是呼叫Calendar的set方法來設定時間,月份的範圍也要是從0-11 */ public TimePickerBuilder setRangDate(Calendar startDate, Calendar endDate) { mPickerOptions.startDate = startDate; mPickerOptions.endDate = endDate; return this; } /** * 設定間距倍數,但是隻能在1.0-4.0f之間 * * @param lineSpacingMultiplier */ public TimePickerBuilder setLineSpacingMultiplier(float lineSpacingMultiplier) { mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier; return this; } /** * 設定分割線的顏色 * * @param dividerColor */ public TimePickerBuilder setDividerColor(int dividerColor) { mPickerOptions.dividerColor = dividerColor; return this; } /** * 設定分割線的型別 * * @param dividerType */ public TimePickerBuilder setDividerType(WheelView.DividerType dividerType) { mPickerOptions.dividerType = dividerType; return this; } /** * //顯示時的外部背景色顏色,預設是灰色 * * @param backgroundId */ public TimePickerBuilder setBackgroundId(int backgroundId) { mPickerOptions.backgroundId = backgroundId; return this; } /** * 設定分割線之間的文字的顏色 * * @param textColorCenter */ public TimePickerBuilder setTextColorCenter(int textColorCenter) { mPickerOptions.textColorCenter = textColorCenter; return this; } /** * 設定分割線以外文字的顏色 * * @param textColorOut */ public TimePickerBuilder setTextColorOut(int textColorOut) { mPickerOptions.textColorOut = textColorOut; return this; } public TimePickerBuilder isCyclic(boolean cyclic) { mPickerOptions.cyclic = cyclic; return this; } /** * 點選外部區域是否隱藏 * @param cancelable * @return */ public TimePickerBuilder setOutSideCancelable(boolean cancelable) { mPickerOptions.cancelable = cancelable; return this; } public TimePickerBuilder setLunarCalendar(boolean lunarCalendar) { mPickerOptions.isLunarCalendar = lunarCalendar; return this; } public TimePickerBuilder setLabel(String label_year, String label_month, String label_day, String label_hours, String label_mins, String label_seconds) { mPickerOptions.label_year = label_year; mPickerOptions.label_month = label_month; mPickerOptions.label_day = label_day; mPickerOptions.label_hours = label_hours; mPickerOptions.label_minutes = label_mins; mPickerOptions.label_seconds = label_seconds; return this; } /** * 設定X軸傾斜角度[ -90 , 90°] * * @param x_offset_year 年 * @param x_offset_month 月 * @param x_offset_day 日 * @param x_offset_hours 時 * @param x_offset_minutes 分 * @param x_offset_seconds 秒 * @return */ public TimePickerBuilder setTextXOffset(int x_offset_year, int x_offset_month, int x_offset_day, int x_offset_hours, int x_offset_minutes, int x_offset_seconds) { mPickerOptions.x_offset_year = x_offset_year; mPickerOptions.x_offset_month = x_offset_month; mPickerOptions.x_offset_day = x_offset_day; mPickerOptions.x_offset_hours = x_offset_hours; mPickerOptions.x_offset_minutes = x_offset_minutes; mPickerOptions.x_offset_seconds = x_offset_seconds; return this; } public TimePickerBuilder isCenterLabel(boolean isCenterLabel) { mPickerOptions.isCenterLabel = isCenterLabel; return this; } /** * @param listener 切換item項滾動停止時,實時回撥監聽。 * @return */ public TimePickerBuilder setTimeSelectChangeListener(OnTimeSelectChangeListener listener) { mPickerOptions.timeSelectChangeListener = listener; return this; } /** * 呼叫build方法構建TimePickerView物件 * @return */ public TimePickerView build() { return new TimePickerView(mPickerOptions); } }
在例項化時可以根據自己需要呼叫相應方法;先看下非自定義佈局的實現;
/**
* 初始化時間滾輪控制元件
*/
private void initTimePicker() {
pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
//選擇回撥
Toast.makeText(MainActivity.this,getTime(date),Toast.LENGTH_LONG).show();
}
})
.setTimeSelectChangeListener(new OnTimeSelectChangeListener() {
@Override
public void onTimeSelectChanged(Date date) {
//時間滾動監控回撥
Log.e("pvTime-->",getTime(date));
}
})
.setType(new boolean[]{true, true, true, true, true, true,})
.isDialog(true)//預設設定false ,內部實現將DecorView 作為它的父控制元件。
.build();
Dialog dialog = pvTime.getDialog();
if(dialog!=null){
FrameLayout.LayoutParams params=new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM
);
params.leftMargin=0;
params.rightMargin=0;
pvTime.getDialogContainerLayout().setLayoutParams(params);
Window dialogWindow = dialog.getWindow();
if(dialogWindow!=null){
//修改動畫樣式
dialogWindow.setWindowAnimations(com.bigkoo.pickerview.R.style.picker_view_slide_anim);
//改成Bottom,底部顯示
dialogWindow.setGravity(Gravity.BOTTOM);
}
}
}
呼叫上面這段程式碼,再呼叫show方法,效果就出來了;
公農曆切換效果:
/**
* 初始化時間選擇器 公農曆切換
* 時間範圍(1900-2100)
*/
private void initLunarPicker() {
//系統當前時間
Calendar selectedDate = Calendar.getInstance();
//開始時間
Calendar startDate = Calendar.getInstance();
startDate.set(1900, 1, 01);
//結束時間
Calendar endDate = Calendar.getInstance();
endDate.set(2100, 2, 28);
//時間選擇器 自定義佈局
pvCustomLunar = new TimePickerBuilder(this, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
String time = getTime(date);
//選中事件回撥
Toast.makeText(MainActivity.this, time, Toast.LENGTH_LONG).show();
}
})
.setDate(selectedDate)//設定選中的時間為系統當前時間
.setRangDate(startDate, endDate)//設定時間返回
.setLayoutRes(R.layout.pickerview_custom_lunar, new CustomListener() {
@Override
public void customLayout(final View v) {
//通過setLayoutRes設定自定義佈局效果
//在customLayout中進行邏輯處理
//完成
TextView tvFinish = v.findViewById(R.id.tv_finish);
tvFinish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//點選完成呼叫returnData方法會觸發onTimeSelect進行回撥
pvCustomLunar.returnData();
//隱藏佈局
pvCustomLunar.dismiss();
}
});
//取消
ImageView ivCancel = v.findViewById(R.id.iv_cancel);
ivCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//隱藏佈局
pvCustomLunar.dismiss();
}
});
//切換農曆
CheckBox cbLunar = v.findViewById(R.id.cb_lunar);
cbLunar.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
pvCustomLunar.setLunarCalendar(!pvCustomLunar.isLunarCalendar());
//自適應寬
setTimePickerChildWeight(v, isChecked ? 0.8f : 1f, isChecked ? 1f : 1.1f);
}
});
}
})
.setType(new boolean[]{true, true, true, false, false, false})//boolean陣列,設定條碼顯示 true顯示,false隱藏
.isCenterLabel(false)
.setDividerColor(Color.RED)//設定分割線顏色
.build();
}
/**
* 公農曆切換後調整寬
*
* @param v
* @param yearWeight
* @param weight
*/
private void setTimePickerChildWeight(View v, float yearWeight, float weight) {
ViewGroup timePicker = (ViewGroup) v.findViewById(R.id.timepicker);
View year = timePicker.getChildAt(0);
LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams) year.getLayoutParams());
lp.weight = yearWeight;
year.setLayoutParams(lp);
for (int i = 1; i < timePicker.getChildCount(); i++) {
View childAt = timePicker.getChildAt(i);
LinearLayout.LayoutParams childLp = ((LinearLayout.LayoutParams) childAt.getLayoutParams());
childLp.weight = weight;
childAt.setLayoutParams(childLp);
}
}
自定義時間選擇器佈局效果:
/**
* @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, 2, 28);
//時間選擇器 ,自定義佈局
pvCustomTime = new TimePickerBuilder(this, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {//選中事件回撥
btnCustomTime.setText(getTime(date));
}
})
.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();
pvCustomTime.dismiss();
}
});
ivCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvCustomTime.dismiss();
}
});
}
})
.setContentTextSize(18)
.setType(new boolean[]{false, false, false, true, true, true})
.setLabel("年", "月", "日", "時", "分", "秒")
.setLineSpacingMultiplier(1.2f)
.setTextXOffset(0, 0, 0, 40, 0, -40)
.isCenterLabel(false) //是否只顯示中間選中項的label文字,false則每項item全部都帶有label。
.setDividerColor(0xFF24AD9D)
.build();
}
<?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="@mipmap/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.contrarywind.view.WheelView
android:id="@+id/year"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.contrarywind.view.WheelView
android:id="@+id/month"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.contrarywind.view.WheelView
android:id="@+id/day"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.contrarywind.view.WheelView
android:id="@+id/hour"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.contrarywind.view.WheelView
android:id="@+id/min"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
<com.contrarywind.view.WheelView
android:id="@+id/second"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.1" />
</LinearLayout>
</LinearLayout>
接下來看下條件選擇器的大致使用,條件選擇器例項化時主要涉及到OptionsPickerView和OptionsPickerBuilder,和時間選擇器一樣採用鏈式程式設計和build設計模式;
public class OptionsPickerBuilder {
//配置類
private PickerOptions mPickerOptions;
//Required
public OptionsPickerBuilder(Context context, OnOptionsSelectListener listener) {
mPickerOptions = new PickerOptions(PickerOptions.TYPE_PICKER_OPTIONS);
mPickerOptions.context = context;
mPickerOptions.optionsSelectListener = listener;
}
//Option
public OptionsPickerBuilder setSubmitText(String textContentConfirm) {
mPickerOptions.textContentConfirm = textContentConfirm;
return this;
}
public OptionsPickerBuilder setCancelText(String textContentCancel) {
mPickerOptions.textContentCancel = textContentCancel;
return this;
}
public OptionsPickerBuilder setTitleText(String textContentTitle) {
mPickerOptions.textContentTitle = textContentTitle;
return this;
}
public OptionsPickerBuilder isDialog(boolean isDialog) {
mPickerOptions.isDialog = isDialog;
return this;
}
public OptionsPickerBuilder setSubmitColor(int textColorConfirm) {
mPickerOptions.textColorConfirm = textColorConfirm;
return this;
}
public OptionsPickerBuilder setCancelColor(int textColorCancel) {
mPickerOptions.textColorCancel = textColorCancel;
return this;
}
/**
* 顯示時的外部背景色顏色,預設是灰色
*
* @param backgroundId color resId.
* @return
*/
public OptionsPickerBuilder setBackgroundId(int backgroundId) {
mPickerOptions.backgroundId = backgroundId;
return this;
}
/**
* ViewGroup 型別
* 設定PickerView的顯示容器
*
* @param decorView Parent View.
* @return
*/
public OptionsPickerBuilder setDecorView(ViewGroup decorView) {
mPickerOptions.decorView = decorView;
return this;
}
public OptionsPickerBuilder setLayoutRes(int res, CustomListener listener) {
mPickerOptions.layoutRes = res;
mPickerOptions.customListener = listener;
return this;
}
public OptionsPickerBuilder setBgColor(int bgColorWheel) {
mPickerOptions.bgColorWheel = bgColorWheel;
return this;
}
public OptionsPickerBuilder setTitleBgColor(int bgColorTitle) {
mPickerOptions.bgColorTitle = bgColorTitle;
return this;
}
public OptionsPickerBuilder setTitleColor(int textColorTitle) {
mPickerOptions.textColorTitle = textColorTitle;
return this;
}
public OptionsPickerBuilder setSubCalSize(int textSizeSubmitCancel) {
mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel;
return this;
}
public OptionsPickerBuilder setTitleSize(int textSizeTitle) {
mPickerOptions.textSizeTitle = textSizeTitle;
return this;
}
public OptionsPickerBuilder setContentTextSize(int textSizeContent) {
mPickerOptions.textSizeContent = textSizeContent;
return this;
}
public OptionsPickerBuilder setOutSideCancelable(boolean cancelable) {
mPickerOptions.cancelable = cancelable;
return this;
}
public OptionsPickerBuilder setLabels(String label1, String label2, String label3) {
mPickerOptions.label1 = label1;
mPickerOptions.label2 = label2;
mPickerOptions.label3 = label3;
return this;
}
/**
* 設定Item 的間距倍數,用於控制 Item 高度間隔
*
* @param lineSpacingMultiplier 浮點型,1.0-4.0f 之間有效,超過則取極值。
*/
public OptionsPickerBuilder setLineSpacingMultiplier(float lineSpacingMultiplier) {
mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier;
return this;
}
/**
* Set item divider line type color.
*
* @param dividerColor color resId.
*/
public OptionsPickerBuilder setDividerColor(int dividerColor) {
mPickerOptions.dividerColor = dividerColor;
return this;
}
/**
* Set item divider line type.
*
* @param dividerType enum Type {@link WheelView.DividerType}
*/
public OptionsPickerBuilder setDividerType(WheelView.DividerType dividerType) {
mPickerOptions.dividerType = dividerType;
return this;
}
/**
* Set the textColor of selected item.
*
* @param textColorCenter color res.
*/
public OptionsPickerBuilder setTextColorCenter(int textColorCenter) {
mPickerOptions.textColorCenter = textColorCenter;
return this;
}
/**
* Set the textColor of outside item.
*
* @param textColorOut color resId.
*/
public OptionsPickerBuilder setTextColorOut(int textColorOut) {
mPickerOptions.textColorOut = textColorOut;
return this;
}
public OptionsPickerBuilder setTypeface(Typeface font) {
mPickerOptions.font = font;
return this;
}
public OptionsPickerBuilder setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
mPickerOptions.cyclic1 = cyclic1;
mPickerOptions.cyclic2 = cyclic2;
mPickerOptions.cyclic3 = cyclic3;
return this;
}
public OptionsPickerBuilder setSelectOptions(int option1) {
mPickerOptions.option1 = option1;
return this;
}
public OptionsPickerBuilder setSelectOptions(int option1, int option2) {
mPickerOptions.option1 = option1;
mPickerOptions.option2 = option2;
return this;
}
public OptionsPickerBuilder setSelectOptions(int option1, int option2, int option3) {
mPickerOptions.option1 = option1;
mPickerOptions.option2 = option2;
mPickerOptions.option3 = option3;
return this;
}
public OptionsPickerBuilder setTextXOffset(int xoffset_one, int xoffset_two, int xoffset_three) {
mPickerOptions.x_offset_one = xoffset_one;
mPickerOptions.x_offset_two = xoffset_two;
mPickerOptions.x_offset_three = xoffset_three;
return this;
}
public OptionsPickerBuilder isCenterLabel(boolean isCenterLabel) {
mPickerOptions.isCenterLabel = isCenterLabel;
return this;
}
/**
* 切換選項時,是否還原第一項
*
* @param isRestoreItem true:還原; false: 保持上一個選項
* @return TimePickerBuilder
*/
public OptionsPickerBuilder isRestoreItem(boolean isRestoreItem) {
mPickerOptions.isRestoreItem = isRestoreItem;
return this;
}
/**
* @param listener 切換item項滾動停止時,實時回撥監聽。
* @return
*/
public OptionsPickerBuilder setOptionsSelectChangeListener(OnOptionsSelectChangeListener listener) {
mPickerOptions.optionsSelectChangeListener = listener;
return this;
}
public <T> OptionsPickerView<T> build() {
return new OptionsPickerView<>(mPickerOptions);
}
}
OptionsPickerBuilder提供了一系列設定方法;根據效果的需要呼叫相應的方法;
先看一般的條件選擇器的效果:
/**
* 初始化條件選擇器
*/
private void initOptionPicker(){
pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
//返回的分別是三個級別的選中位置
String tx = options1Items.get(options1).getPickerViewText()
+ options2Items.get(options1).get(options2);
btnOptions.setText(tx);
}
})
.setTitleText("城市選擇")//設定標題
.setContentTextSize(20)//設定滾輪文字大小
.setDividerColor(Color.LTGRAY)//設定分割線的顏色
.setSelectOptions(0, 1)//預設選中項
.setBgColor(Color.BLACK)//設定背景色
.setTitleBgColor(Color.DKGRAY)//設定標題背景色
.setTitleColor(Color.LTGRAY)//設定標題顏色
.setCancelColor(Color.YELLOW)//設定取消字型顏色
.setSubmitColor(Color.YELLOW)//設定提交字型顏色
.setTextColorCenter(Color.LTGRAY)//設定中間字型顏色
.isRestoreItem(true)//切換時是否還原,設定預設選中第一項。
.isCenterLabel(false) //是否只顯示中間選中項的label文字,false則每項item全部都帶有label。
.setLabels("省", "市", "區")
.setBackgroundId(0x00000000) //設定外部遮罩顏色
.setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() {
@Override
public void onOptionsSelectChanged(int options1, int options2, int options3) {
String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3;
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
})
.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 OptionsPickerBuilder(this, new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3, View v) {
//返回的分別是三個級別的選中位置
String tx = cardItem.get(options1).getPickerViewText();
btnCustomOptions.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();
pvCustomOptions.dismiss();
}
});
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 initNoLinkOptionsPicker() {
pvNoLinkOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int options2, int options3, View v) {
String str = "food:" + food.get(options1)
+ "\nclothes:" + clothes.get(options2)
+ "\ncomputer:" + computer.get(options3);
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
})
.setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() {
@Override
public void onOptionsSelectChanged(int options1, int options2, int options3) {
String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3;
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
})
// .setSelectOptions(0, 1, 1)
.build();
pvNoLinkOptions.setNPicker(food, clothes, computer);
pvNoLinkOptions.setSelectOptions(0, 1, 1);
}
最後來看下城市地址選擇效果的實現:
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();
}
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LOAD_DATA:
if (thread == null) {//如果已建立就不再重新建立子執行緒了
Toast.makeText(JsonDataActivity.this, "Begin Parse Data", 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, "Parse Succeed", Toast.LENGTH_SHORT).show();
isLoaded = true;
break;
case MSG_LOAD_FAILED:
Toast.makeText(JsonDataActivity.this, "Parse Failed", 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, "Please waiting until the data is parsed", Toast.LENGTH_SHORT).show();
}
break;
}
}
private void showPickerView() {// 彈出選擇器
OptionsPickerView pvOptions = new OptionsPickerBuilder(this, new 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)
.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 {
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);
}
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;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
}
}