天天看點

android 指定多種類型的屬性,pickerview-一個非常好用的Android PickerView庫,内部提供3種常用類型的Picker。支援擴充自定義Picker。...

一個非常好用的Android PickerView庫,内部提供3種常用類型的Picker。支援擴充自定義Picker。TimePicker:時間選擇器,包含日期

MixedTimePicker::聚合的時間選擇器

OptionPicker:關聯選擇器

Screenshot

android 指定多種類型的屬性,pickerview-一個非常好用的Android PickerView庫,内部提供3種常用類型的Picker。支援擴充自定義Picker。...
android 指定多種類型的屬性,pickerview-一個非常好用的Android PickerView庫,内部提供3種常用類型的Picker。支援擴充自定義Picker。...
android 指定多種類型的屬性,pickerview-一個非常好用的Android PickerView庫,内部提供3種常用類型的Picker。支援擴充自定義Picker。...

APK

Picker

通過組裝PickerView實作常用的Picker選擇器。上面已經列舉提供的3中常用的Picker。

BasePicker

Picker基類:封裝了TopBar,PickerView容器,create and add PickerView方法,Picker彈窗等方法。 三種Picker都繼承自BasePicker,你也可以繼承它擴充自己的Picker。

APIapidescriptionsetPickerBackgroundColor設定picker背景

setPadding設定PickerView父容器padding 機關:px

setTag給Picker 設定tag,用于區分不同的picker等。用法同View setTag

getRootLayout擷取PickerView的父容器,建立DefaultTopBar時必須指定

setOnPickerChooseListener設定picker取消,确定按鈕監聽。可用于攔截選中操作

setTopBar設定自定義TopBar

setInterceptor設定攔截器

createPickerView建立PickerView

getPickerViews擷取Picker中所有的pickerview集合

addPicker将建立的PickerView 添加到上面集合中,createPickerView内部已調用該方法

findPickerViewByTag通過tag找到對應的PickerView

isScrolling是否滾動未停止。滾動未停止的時候,不響應Picker的取消,确定按鍵

getPickerDialog擷取Picker彈窗。可以在new之後設定dialog屬性

show顯示picker彈窗對比github上最受歡迎的同類庫 Android-PickerView 本庫将TopBar等通用相關邏輯封裝在基類中,并提供代碼中建立PickerView方法,不需要再依賴xml。使用者自定義Picker時,繼承BasePicker,隻需要處理自己的邏輯即可,簡單便捷。 而對Android-PickerView來說,實作自定義Picker,依然需要處理TopBar等邏輯。造成大量重複代碼。

TopBar

TopBar:TopBar通過抽象接口ITopBar來管理,實作Picker與TopBar的解耦。提供預設實作DefaultTopBar。可實作接口定制自己的TopBar。public interface ITopBar {

View getTopBarView();

View getBtnCancel();

View getBtnConfirm();

TextView getTitleView();

}

DefaultTopBar APIapidescriptionsetDividerColor設定topbar bottom line color

setDividerHeight設定bottom divider line height

getDivider擷取TopBar bottom line

getTitleView擷取TopBar title view

Interceptor

攔截器:用于在pickerview建立時攔截,設定pickerview的屬性。Picker内部并不提供對PickerView的設定方法,而是通過Interceptor實作。這種設計用來實作Picker和PickerView的屬性設定完美解耦。private void init(){

mTimePicker.setInterceptor(new BasePicker.Interceptor() {

@Override public void intercept(PickerView pickerView) {

pickerView.setVisibleItemCount(5);

// 将年月設定為循環的

int type = (int) pickerView.getTag();

if (type == TimePicker.TYPE_YEAR || type == TimePicker.TYPE_MONTH) {

pickerView.setIsCirculation(true);

}

}

})

}

這一點對比 Android-PickerView, 每個Picker都需要聲明對PickerView的設定方法,與PickerView嚴重耦合。需要開發者copy大量重複代碼,且無法區分每一個PickerView設定不同的屬性。

TimePicker

常用的時間選擇器,支援 年、月、日、時、分時間類型type的設計:自由組合、随心所欲(當然應該是有意義的)TYPE_YEAR | TYPE_MONTH | TYPE_DAY | TYPE_HOUR | TYPE_MINUTE

對比 Android-PickerView TimePickerView

setType(boolean[] type)

// 本項目設定type方法:簡單易懂,組合友善

setType(TYPE_DATE | TYPE_HOUR)完美支援時間區間設定以及選中關聯

支援Format,如顯示今年,明年

APIapidescriptiontype時間類型,需要在Builder構造方法中指定,不能改變

OnTimeSelectListener選中時間回調,需要在Builder構造方法中指定,不能改變

setRangDate設定起止時間

setSelectedDate設定選中時間戳

setInterceptor設定攔截器

setFormatter設定Formatter,内部提供預設的Formatter

create通過Builder建構 TimePicker

以上是TimePicker.Builder的,下面是TimePicker的

setFormatter同上

setSelectedDate同上

getType擷取type

hasType判斷是否包含某種type

Formatter

TimePicker Formatter:用于根據type和num格式化時間文案public interface Formatter {

CharSequence format(TimePicker picker, int type, int position, int num);

}

内部提供預設的 Formatter實作DefaultFormatter。使用者可以設定自定義Formatter或繼承DefaultFormatter進行擴充。TimePicker初始化,如果未設定時間區間,會使用預設區間。三種Picker都采用Builder模式初始化。且使用者自定義的Picker也應該采用這種模式進行初始化。

Simple ExamplemTimePicker = new TimePicker.Builder(mActivity, type, this)

// 設定時間區間

.setRangDate(1526361240000L, 1893563460000L)

// 設定選中時間

//.setSelectedDate()

// 設定pickerview樣式

.setInterceptor(new BasePicker.Interceptor() {

@Override public void intercept(PickerView pickerView) {

pickerView.setVisibleItemCount(5);

// 将年月設定為循環的

int type = (int) pickerView.getTag();

if (type == TimePicker.TYPE_YEAR || type == TimePicker.TYPE_MONTH) {

pickerView.setIsCirculation(true);

}

}

})

// 設定 Formatter

.setFormatter(new TimePicker.DefaultFormatter() {

// 自定義Formatter顯示去年,今年,明年

@Override public CharSequence format(TimePicker picker, int type, int position, int num) {

if (type == TimePicker.TYPE_YEAR) {

int offset = num - mCurrYear;

if (offset == -1) return "去年";

if (offset == 0) return "今年";

if (offset == 1) return "明年";

return num + "年";

}

return super.format(picker, type, position, num);

}

}).create();

//mTimePicker.setSelectedDate(1549349843000L);

mTimePicker.show();

MixedTimePicker

常用的聚合時間選擇器。日期(年、月、日)聚合,時間(小時、分鐘)聚合。混合模式:github上的TimePicker庫基本都不提供該種類型的Picker

支援自定義日期格式,時間格式

支援設定時間間隔

支援設定區間以及選中關聯

支援設定純日期,純時間模式,采用type同TimePicker

APIapidescriptiontype類型,需要在Builder構造方法中指定,不能改變

OnTimeSelectListener選中時間回調,需要在Builder構造方法中指定,不能改變

setRangDate設定起止時間

setSelectedDate設定選中時間戳

setTimeMinuteOffset設定時間間隔分鐘數(60%offset==0才有效),以0為起始邊界

setContainsStarDate設定mTimeMinuteOffset作用時,是否包含超出的startDate

setContainsEndDate設定mTimeMinuteOffset作用時,是否包含超出的endDate

setInterceptor設定攔截器

setFormatter設定Formatter,内部提供預設的Formatter

create通過Builder建構 MixedTimePicker

以上是MixedTimePicker.Builder的,下面是MixedTimePicker的

setFormatter同上

setSelectedDate同上

getType擷取type

hasType判斷是否包含某種type

Formatter

MixedTimePicker Formatter:用于自定義日期和時間格式。内部提供預設的 Formatter實作。public interface Formatter {

CharSequence format(MixedTimePicker picker, int type, Date date, int position);

}MixedTimePicker 的 Formatter 完美展現了Formatter設計的精妙之處。使用者可以根據回調中的type和date自定義日期和時間格式。比如顯示今天,或 xx月xx日 星期 x

Simple ExamplemTimePicker = new MixedTimePicker.Builder(mActivity, MixedTimePicker.TYPE_ALL, this)

// 設定不包含超出的結束時間<=

.setContainsEndDate(false)

// 設定時間間隔為30分鐘

.setTimeMinuteOffset(30)

.setRangDate(1517771651000L, 1577976666000L)

.setFormatter(new MixedTimePicker.DefaultFormatter() {

@Override

public CharSequence format(MixedTimePicker picker, int type, Date date, int position) {

if (type == MixedTimePicker.TYPE_DATE) {

CharSequence text;

int dayOffset = DateUtil.getDayOffset(date.getTime(), System.currentTimeMillis());

if (dayOffset == 0) {

text = "今天";

} else if (dayOffset == 1) {

text = "明天";

} else { // xx月xx日 星期 x

text = mDateFormat.format(date);

}

return text;

}

return super.format(picker, type, date, position);

}

})

.create();

// 2018/2/5 03:14:11 - 2020/1/2 22:51:6

Dialog pickerDialog = mTimePicker.getPickerDialog();

pickerDialog.setCanceledOnTouchOutside(true);

DefaultTopBar topBar = (DefaultTopBar) mTimePicker.getTopBar();

topBar.getTitleView().setText("請選擇時間");不同于TimePicker, MixedTimePicker 由于支援純時間模式(日期取選中時間的日期),不提供預設區間。如果模式中包含日期模式,則會強制要求設定時間區間

OptionPicker支援設定層級

構造資料源及其簡單,隻需要實作OptionDataSet接口

支援通過對應選中的values設定選中項。内部處理選中項邏輯,避免使用者記錄下标且麻煩的周遊處理對比 Android-PickerView的 OptionsPickerViewfunctionAndroid-PickerViews本控件多級最多支援3級(寫死的)構造時設定級别(無限制)

構造資料源需要建構每一級的集合,二三級為嵌套一級資料entity實作OptionDataSet接口即可

設定資料源提供三個方法,分别用于一、二、三級的隻需要設定一級資料集

關聯選中提供三個,隻能設定選中的下标。需要使用者自己通過多層周遊定位每一級别選中的下标,然後再設定隻需要傳入選中的values(可變長數組),不需要任何計算

Android-PickerView 中的 OptionsPickerView 代碼。由于不知道層級,是以每個方法都提供3個用來對應(最多)3級選擇。// 提供3個選中的方法,分别對應1,2,3級關聯的情況

public void setSelectOptions(int option1)

public void setSelectOptions(int option1, int option2)

public void setSelectOptions(int option1, int option2, int option3)

// 提供3個設定資料源的方法,分别對應1,2,3級關聯的情況

public void setPicker(List optionsItems)

public void setPicker(List options1Items, List> options2Items)

public void setPicker(List options1Items, List> options2Items,

List>> options3Items) {

}

本庫中的OptionPicker

public void setDataWithValues(List extends OptionDataSet> options, String... values) {

mOptions = options;

setSelectedWithValues(values);

}

public void setSelectedWithValues(String... values) {

...

}如上面對比表格中所列舉的,無論是層級,構造資料源和設定資料源,還是設定選中的選項,本庫的API都十分簡單,友善。

APIapidescriptionmHierarchy層級,需要在Builder構造方法中指定,不能改變

OnOptionSelectListener選中回調,需要在Builder構造方法中指定,不能改變

setInterceptor設定攔截器

setFormatter設定Formatter

create通過Builder建構 OptionPicker

以上是OptionPicker.Builder的,下面是OptionPicker的

setFormatter同上

setDataWithValues根據選中的values初始化選中的position并初始化pickerview資料。values參數為可變長數組,可以不設定。

setDataWithIndexs設定資料和選中position。不建議使用,建議使用 setDataWithValues

setSelectedWithValues根據選中的values初始化選中的position

setSelectedWithIndexs設定選中的position。不建議使用,建議使用 setSelectedWithValues

getOptions擷取資料集

getSelectedPosition擷取選中的下标,數組size=mHierarchy,如果為-1表示該列沒有資料

getSelectedOptions擷取選中的選項,如果指定index為null則表示該列沒有資料需要注意的是:本庫中的OptionPicker隻用于關聯的,不支援多級别且不關聯。 基本沒有這種需求,如果大家有這種需求,我會在後續疊代中支援。

Others奇葩設計:部分default屬性聲明為static而非final

全局設定default屬性

奇葩也好,亮點也罷。作為一個UI控件,不同的app,不同的UI,不同的産品自然會有不同的樣式。 考慮到在一個app中我們會用到很多Picker,而我們又需要定制自己的UI的樣式,如果通過動态方法設定樣式就太麻煩了。 故做此設計。你可以通過配置這些static變量來快速定制一個滿足自己app樣式需求的Picker。 當然你也可以通過封裝方法來處理PickerView,Picker,裝飾器等樣式,但這樣一樣十分麻煩。我相信你自己都會煩。

靜态預設值所有的這些靜态屬性值都以 sDefault 開頭BasePickerViewfielddescriptiondefaultValuesDefaultVisibleItemCount預設可見的item個數5

sDefaultItemSize預設itemSize50(dp)

sDefaultIsCirculation預設是否循環falsePickerViewfielddescriptiondefaultValuesOutTextSizedefault out text size18(dp)

sCenterTextSizedefault center text size22(dp)

sCenterColordefault center text colorColor.BLUE

sOutColordefault out text colorColor.GRAYBasePickerfielddescriptiondefaultValuesDefaultPaddingRectpickerView父容器的 default paddingnull(無padding)

sDefaultPickerBackgroundColordefault picker background colorColor.WHITE

sDefaultTopBarCreator用于建構自定義defaultTopBar的接口nullDefaultCenterDecorationfielddescriptiondefaultValuesDefaultLineColordefault line colorColor.BLUE

sDefaultLineWidthdefault line width1(dp)

sDefaultDrawabledefault item background drawablenull

sDefaultMarginRectdefault line marginnull(無margin)建議初始化這些屬性值放到Application中完成,避免app發生crash而導緻失效

Simple Examplepublic class MyApplication extends Application {

@Override public void onCreate() {

super.onCreate();

// 建議在application中初始化picker 預設屬性實作全局設定

initDefaultPicker();

}

private void initDefaultPicker() {

// 利用修改靜态預設屬性值,快速定制一套滿足自己app樣式需求的Picker.

// BasePickerView

PickerView.sDefaultVisibleItemCount = 3;

PickerView.sDefaultItemSize = 50;

PickerView.sDefaultIsCirculation = true;

// PickerView

PickerView.sOutTextSize = 18;

PickerView.sCenterTextSize = 18;

PickerView.sCenterColor = Color.RED;

PickerView.sOutColor = Color.GRAY;

// BasePicker

int padding = Util.dip2px(this, 20);

BasePicker.sDefaultPaddingRect = new Rect(padding, padding, padding, padding);

BasePicker.sDefaultPickerBackgroundColor = Color.WHITE;

// 自定義 TopBar

BasePicker.sDefaultTopBarCreator = new BasePicker.IDefaultTopBarCreator() {

@Override public ITopBar createDefaultTopBar(LinearLayout parent) {

return new CustomTopBar(parent);

}

};

// DefaultCenterDecoration

DefaultCenterDecoration.sDefaultLineWidth = 1;

DefaultCenterDecoration.sDefaultLineColor = Color.RED;

//DefaultCenterDecoration.sDefaultDrawable = new ColorDrawable(Color.WHITE);

int leftMargin = Util.dip2px(this, 10);

int topMargin = Util.dip2px(this, 2);

DefaultCenterDecoration.sDefaultMarginRect =

new Rect(leftMargin, -topMargin, leftMargin, -topMargin);

}

}