一、首先引入依赖库
//时间选择器implementation 'io.github.ShawnLin013:number-picker:2.4.13'
二、自定义时间选择器
public class TimePickerCustom {private final BottomSheetDialog bottomDialog;private final NumberPicker year;private final NumberPicker month;private final NumberPicker day;/*** 时间选择回调**/public interface TimePickerCallback {/*** 回调** @param year 年* @param month 月* @param day 日*/void setDate(int year, int month, int day);}public TimePickerCustom(Context context, String title, TimePickerCallback callback) {// 设置时间选择器的布局以及弹窗的高度bottomDialog = getBottomDialog(context, R.layout.view_time_picker, dpToPx(context, 350));Calendar calendar = Calendar.getInstance();// 设置标题((TextView)bottomDialog.findViewById(R.id.title)).setText(title);// 年year = (NumberPicker)bottomDialog.findViewById(R.id.year);int yearNow = calendar.get(Calendar.YEAR);year.setMinValue(yearNow - 100);year.setMaxValue(yearNow + 100);year.setValue(yearNow);// 月month = (NumberPicker)bottomDialog.findViewById(R.id.month);String[] monthNum = new String[12];for (int i = 0; i < 12; i++) {monthNum[i] = (i + 1) + "月";}month.setMinValue(1);month.setMaxValue(monthNum.length);month.setDisplayedValues(monthNum);month.setValue(calendar.get(Calendar.MONTH));// 日day = (NumberPicker)bottomDialog.findViewById(R.id.day);day.setMinValue(1);int days = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);String[] newDays = getNewDays(days);day.setMaxValue(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));day.setDisplayedValues(newDays);day.setValue(calendar.get(Calendar.DATE));// 年份和月份更改时对应的天数需要更改year.setOnValueChangedListener((picker, oldVal, newVal) -> {updateNumberOfDays();day.setValue(calendar.get(Calendar.DATE));});month.setOnValueChangedListener((picker, oldVal, newVal) -> {updateNumberOfDays();day.setValue(calendar.get(Calendar.DATE));});// 取消按钮和确定按钮事件绑定View cancel = bottomDialog.findViewById(R.id.cancel);View ok = bottomDialog.findViewById(R.id.ok);if (cancel != null) {cancel.setOnClickListener(v -> bottomDialog.dismiss());}if (ok != null) {ok.setOnClickListener(v -> {bottomDialog.dismiss();callback.setDate(year.getValue(), month.getValue(), day.getValue());});}}/*** 底部弹出框** @param id 弹窗中的布局* @param height 弹窗高度*/private BottomSheetDialog getBottomDialog(Context context, Integer id, int height) {BottomSheetDialog bottomSheet = new BottomSheetDialog(context);// 设置对框框中的布局bottomSheet.setContentView(id);// 设置点击外部是否可以取消bottomSheet.setCancelable(true);FrameLayout bottom = (FrameLayout)bottomSheet.findViewById(com.google.android.material.R.id.design_bottom_sheet);if (bottom != null) {// 设置背景透明颜色bottom.setBackgroundResource(R.color.transparent);// 修改弹窗的高度ViewGroup.LayoutParams layoutParams = bottom.getLayoutParams();layoutParams.height = height;bottom.setLayoutParams(layoutParams);}return bottomSheet;}/*** dp转px*/private int dpToPx(Context context, float dp) {return (int)(dp * context.getResources().getDisplayMetrics().density + 0.5);}/*** 显示*/public void show() {bottomDialog.show();}/*** 设置选中年份** @param yearValue 年*/public void setYearValue(int yearValue) {year.setValue(yearValue);updateNumberOfDays();}/*** 设置选中月份** @param monthValue 月*/public void setMonthValue(int monthValue) {month.setValue(monthValue);updateNumberOfDays();}/*** 设置选中天数** @param dayValue 天*/public void setDayValue(int dayValue) {day.setValue(dayValue);}/*** 更新天数**/private void updateNumberOfDays() {Calendar calendar = Calendar.getInstance();calendar.set(Calendar.YEAR, year.getValue());calendar.set(Calendar.MONTH, (month.getValue() - 1));calendar.set(Calendar.DATE, 1);calendar.roll(Calendar.DATE, -1);int date = calendar.get(Calendar.DATE);day.setMaxValue(date);day.setDisplayedValues(getNewDays(date));}/*** 格式化天数** @param days 天数* @return {@link String[]}*/private String[] getNewDays(int days) {List<String> dayList = new ArrayList<>();for (int i = 0; i < days; i++) {dayList.add((i + 1) + "日");}return dayList.toArray(new String[dayList.size()]);}}
对应view_time_picker.xml布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:background="@drawable/bg_bottom_dialog"><TextViewandroid:id="@+id/cancel"android:layout_width="wrap_content"android:layout_height="40dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintBottom_toTopOf="@id/year"android:gravity="center"android:text="取消"android:textColor="#666666"android:clickable="true"android:focusable="true" /><TextViewandroid:id="@+id/title"android:layout_width="0dp"android:layout_height="40dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintLeft_toRightOf="@id/cancel"app:layout_constraintBottom_toTopOf="@id/year"app:layout_constraintRight_toLeftOf="@id/ok"android:gravity="center"android:text="出生日期"android:textColor="#333333"android:textStyle="bold" /><TextViewandroid:id="@+id/ok"android:layout_width="wrap_content"android:layout_height="40dp"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toTopOf="@id/year"android:gravity="center"android:text="确定"android:textColor="#1580C8"android:textStyle="bold"android:clickable="true"android:focusable="true" /><com.shawnlin.numberpicker.NumberPickerandroid:id="@+id/year"android:layout_width="0dp"android:layout_height="0dp"app:layout_constraintTop_toBottomOf="@id/title"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toLeftOf="@id/month"app:np_formatter="%d"app:np_dividerColor="#2B000000"app:np_dividerThickness="1px"app:np_selectedTextColor="#333333"app:np_selectedTextSize="18sp"app:np_textSize="14sp"app:np_wheelItemCount="5"app:np_wrapSelectorWheel="false" /><com.shawnlin.numberpicker.NumberPickerandroid:id="@+id/month"android:layout_width="0dp"android:layout_height="0dp"app:layout_constraintTop_toBottomOf="@id/title"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toRightOf="@id/year"app:layout_constraintRight_toLeftOf="@id/day"app:np_dividerColor="#2B000000"app:np_dividerThickness="1px"app:np_selectedTextColor="#333333"app:np_selectedTextSize="18sp"app:np_textSize="14sp"app:np_wheelItemCount="5"app:np_wrapSelectorWheel="false" /><com.shawnlin.numberpicker.NumberPickerandroid:id="@+id/day"android:layout_width="0dp"android:layout_height="0dp"app:layout_constraintTop_toBottomOf="@id/title"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toRightOf="@id/month"app:layout_constraintRight_toRightOf="parent"app:np_dividerColor="#2B000000"app:np_dividerThickness="1px"app:np_selectedTextColor="#333333"app:np_selectedTextSize="18sp"app:np_textSize="14sp"app:np_wheelItemCount="5"app:np_wrapSelectorWheel="false" /></androidx.constraintlayout.widget.ConstraintLayout>
用法
在Mactivity或者Fragment直接调用
TimePickerCustom timePickerCustom = new TimePickerCustom(PersonalInfoActivity.this, "时间选择", (year, month, day) -> {Log.i("timePickerCustom", year + "------" + month + "--------" + day);Message msg = new Message();msg.what = 2;msg.obj = year+"/" + month + "/" + day;handler.sendMessage(msg);});timePickerCustom.show();