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ì)偏紅)