android_基础_日期选择器 DatePicker and TimePicker

转载自: https://www.jianshu.com/p/05dade729e28

Android构建自定义日期时间选择器

Android开发中有时会用到日期和时间的选择,系统自带的有DatePicker和TimePicker两种,但是当我们需要同时选择日期和时间时,自带的选择器就存在比较大的问题。

<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>

当我们将两个选择器放在同一行,方便页面进行适配时发现,自带的选择器空间无法调整大小,两个选择器都会采用默认宽高,使得部分内容无法显示。

在这里插入图片描述

因此最好的办法还自定义一个时间日期选择器,同时也能方便以后进行样式修改美化。

系统自带的选择器还有一个NumberPicker,我们可以使用这个控件,结合其他控件做出想要的效果。
部分实现代码如下:
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文件中自定义控件样式,为每个控件排好位置。再通过代码对每个NumberPicker进行限制。
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);  //关闭选择器循环

//设置月份范围为1~12
monthPicker.setMinValue(1);
monthPicker.setMaxValue(12);
monthPicker.setValue(calendar.get(Calendar.MONTH) + 1);
monthPicker.setWrapSelectorWheel(false);

//日期限制存在变化,需要根据当月最大天数来调整
datePicker.setMinValue(1);
datePicker.setMaxValue(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
datePicker.setValue(calendar.get(Calendar.DATE));
datePicker.setWrapSelectorWheel(false);

//24小时制,限制小时数为0~23
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY));
hourPicker.setWrapSelectorWheel(false);

//限制分钟数为0~59
minutePicker.setMinValue(0);
minutePicker.setMaxValue(59);
minutePicker.setValue(calendar.get(Calendar.MINUTE));
minutePicker.setWrapSelectorWheel(false);

//为年份和月份设置监听
yearPicker.setOnValueChangedListener(this);
monthPicker.setOnValueChangedListener(this);

当选择器日期发生变化时,我们需要判断所显示的日期月份最多有多少天,防止出现不存在日期的情况,这时就需要为选择器值变动监听,因为年份和月份的变动都会影响当月最大天数,因此可以通过实现NumberPicker.OnValueChangeListener,重写onValueChange()方法来实现:

@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);
    //重设日期值,防止月份变动时超过最大值
    datePicker.setValue(Math.min(dateValue, maxValue));
}

这样一个自定义的可以同时选择日期和时间的选择器就基本完工了,以后还能自定义各个控件的样式来实现想要的效果。当然,获取选择器的结果可以通过定义一个Button来监听点击事件来获取

findViewById(R.id.button_confirm).setOnClickListener(view -> {
    //获取的日期时间结果
    String result = String.format(Locale.CHINA, "%d-%d-%d %d:%d",
            yearPicker.getValue(), monthPicker.getValue(), datePicker.getValue(),
            hourPicker.getValue(), minutePicker.getValue());
    ...
}

最后来看一下显示效果吧(PS:不知道为啥转gif会偏红)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42420293/article/details/121412098
今日推荐