Android構(gòu)建自定義日期時(shí)間選擇器

Android開發(fā)中有時(shí)會(huì)用到日期和時(shí)間的選擇成翩,系統(tǒng)自帶的有DatePicker和TimePicker兩種,但是當(dāng)我們需要同時(shí)選擇日期和時(shí)間時(shí)叮雳,自帶的選擇器就存在比較大的問(wèn)題想暗。

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp" >

    <DatePicker
        android:id="@+id/date_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:calendarViewShown="false"
        android:datePickerMode="spinner"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TimePicker
        android:id="@+id/time_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:timePickerMode="spinner"
        app:layout_constraintStart_toEndOf="@id/date_picker"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

當(dāng)我們將兩個(gè)選擇器放在同一行,方便頁(yè)面進(jìn)行適配時(shí)發(fā)現(xiàn)债鸡,自帶的選擇器空間無(wú)法調(diào)整大小江滨,兩個(gè)選擇器都會(huì)采用默認(rèn)寬高,使得部分內(nèi)容無(wú)法顯示厌均。


界面截圖

因此最好的辦法還自定義一個(gè)時(shí)間日期選擇器唬滑,同時(shí)也能方便以后進(jìn)行樣式修改美化。

系統(tǒng)自帶的選擇器還有一個(gè)NumberPicker棺弊,我們可以使用這個(gè)控件晶密,結(jié)合其他控件做出想要的效果。
部分實(shí)現(xiàn)代碼如下:
dialog_fragment_date_time_picker.xml

<LinearLayout
    android:id="@+id/item_linear_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginEnd="16dp"
    android:gravity="fill_horizontal">

    <NumberPicker
        android:id="@+id/number_picker_year"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.2"
        android:descendantFocusability="blocksDescendants" />

    <TextView
        android:id="@+id/text_view_year"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.05"
        android:gravity="center"
        android:text="@string/text_year" />

    <NumberPicker
        android:id="@+id/number_picker_month"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.15"
        android:descendantFocusability="blocksDescendants" />

    <TextView
        android:id="@+id/text_view_month"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.05"
        android:gravity="center"
        android:text="@string/text_month" />

    <NumberPicker
        android:id="@+id/number_picker_date"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.15"
        android:descendantFocusability="blocksDescendants" />

    <TextView
        android:id="@+id/text_view_date"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.05"
        android:gravity="center"
        android:text="@string/text_date" />

    <NumberPicker
        android:id="@+id/number_picker_hour"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.15"
        android:descendantFocusability="blocksDescendants" />

    <TextView
        android:id="@+id/text_view_hour"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.05"
        android:gravity="center"
        android:text="@string/text_time_symbol" />

    <NumberPicker
        android:id="@+id/number_picker_minute"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:layout_weight="0.15"
        android:descendantFocusability="blocksDescendants" />

</LinearLayout>

先在xml文件中自定義控件樣式模她,為每個(gè)控件排好位置稻艰。再通過(guò)代碼對(duì)每個(gè)NumberPicker進(jìn)行限制。
DateTimePickerDialogFragment.java

Calendar calendar = Calendar.getInstance();
NumberPicker yearPicker = findViewById(R.id.number_picker_year);
NumberPicker monthPicker = findViewById(R.id.number_picker_month);
NumberPicker datePicker = findViewById(R.id.number_picker_date);
NumberPicker hourPicker = findViewById(R.id.number_picker_hour);
NumberPicker minutePicker = findViewById(R.id.number_picker_minute);

//限制年份范圍為前后五年
int yearNow = calendar.get(Calendar.YEAR);
yearPicker.setMinValue(yearNow - 5);
yearPicker.setMaxValue(yearNow + 5);
yearPicker.setValue(yearNow);
yearPicker.setWrapSelectorWheel(false);  //關(guān)閉選擇器循環(huán)

//設(shè)置月份范圍為1~12
monthPicker.setMinValue(1);
monthPicker.setMaxValue(12);
monthPicker.setValue(calendar.get(Calendar.MONTH) + 1);
monthPicker.setWrapSelectorWheel(false);

//日期限制存在變化侈净,需要根據(jù)當(dāng)月最大天數(shù)來(lái)調(diào)整
datePicker.setMinValue(1);
datePicker.setMaxValue(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
datePicker.setValue(calendar.get(Calendar.DATE));
datePicker.setWrapSelectorWheel(false);

//24小時(shí)制尊勿,限制小時(shí)數(shù)為0~23
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY));
hourPicker.setWrapSelectorWheel(false);

//限制分鐘數(shù)為0~59
minutePicker.setMinValue(0);
minutePicker.setMaxValue(59);
minutePicker.setValue(calendar.get(Calendar.MINUTE));
minutePicker.setWrapSelectorWheel(false);

//為年份和月份設(shè)置監(jiān)聽(tīng)
yearPicker.setOnValueChangedListener(this);
monthPicker.setOnValueChangedListener(this);

當(dāng)選擇器日期發(fā)生變化時(shí)僧凤,我們需要判斷所顯示的日期月份最多有多少天,防止出現(xiàn)不存在日期的情況元扔,這時(shí)就需要為選擇器值變動(dòng)監(jiān)聽(tīng)躯保,因?yàn)槟攴莺驮路莸淖儎?dòng)都會(huì)影響當(dāng)月最大天數(shù),因此可以通過(guò)實(shí)現(xiàn)NumberPicker.OnValueChangeListener澎语,重寫onValueChange()方法來(lái)實(shí)現(xiàn):

@Override
public void onValueChange(NumberPicker numberPicker, int i, int i1) {
    String dateStr = String.format(Locale.CHINA, "%d-%d", yearPicker.getValue(), monthPicker.getValue());
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM", Locale.CHINA);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(simpleDateFormat.parse(dateStr));
    int dateValue = datePicker.getValue();
    int maxValue = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    datePicker.setMaxValue(maxValue);
    //重設(shè)日期值途事,防止月份變動(dòng)時(shí)超過(guò)最大值
    datePicker.setValue(Math.min(dateValue, maxValue));
}

這樣一個(gè)自定義的可以同時(shí)選擇日期和時(shí)間的選擇器就基本完工了,以后還能自定義各個(gè)控件的樣式來(lái)實(shí)現(xiàn)想要的效果擅羞。當(dāng)然尸变,獲取選擇器的結(jié)果可以通過(guò)定義一個(gè)Button來(lái)監(jiān)聽(tīng)點(diǎn)擊事件來(lái)獲取

findViewById(R.id.button_confirm).setOnClickListener(view -> {
    //獲取的日期時(shí)間結(jié)果
    String result = String.format(Locale.CHINA, "%d-%d-%d %d:%d",
            yearPicker.getValue(), monthPicker.getValue(), datePicker.getValue(),
            hourPicker.getValue(), minutePicker.getValue());
    ...
}

最后來(lái)看一下顯示效果吧(PS:不知道為啥轉(zhuǎn)gif會(huì)偏紅)


Screenshot.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市减俏,隨后出現(xiàn)的幾起案子召烂,更是在濱河造成了極大的恐慌,老刑警劉巖垄懂,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骑晶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡草慧,警方通過(guò)查閱死者的電腦和手機(jī)桶蛔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)漫谷,“玉大人仔雷,你說(shuō)我怎么就攤上這事√蚴荆” “怎么了碟婆?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)惕稻。 經(jīng)常有香客問(wèn)我竖共,道長(zhǎng),這世上最難降的妖魔是什么俺祠? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任公给,我火速辦了婚禮,結(jié)果婚禮上蜘渣,老公的妹妹穿的比我還像新娘淌铐。我一直安慰自己,他們只是感情好蔫缸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布腿准。 她就那樣靜靜地躺著,像睡著了一般拾碌。 火紅的嫁衣襯著肌膚如雪吐葱。 梳的紋絲不亂的頭發(fā)上街望,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音弟跑,去河邊找鬼它匕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛窖认,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播告希,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼扑浸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了燕偶?” 一聲冷哼從身側(cè)響起喝噪,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎指么,沒(méi)想到半個(gè)月后酝惧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伯诬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年晚唇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盗似。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哩陕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赫舒,到底是詐尸還是另有隱情悍及,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布接癌,位于F島的核電站心赶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缺猛。R本人自食惡果不足惜缨叫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枯夜。 院中可真熱鬧弯汰,春花似錦、人聲如沸湖雹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)摔吏。三九已至鸽嫂,卻和暖如春纵装,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背据某。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工橡娄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人癣籽。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓挽唉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親筷狼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瓶籽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353