自定义时间选择器
布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cl_time_date_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent">
<ImageView
android:id="@+id/iv_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/bg_time_date_left"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="@dimen/common_190dp"
android:layout_height="@dimen/common_30dp"
android:layout_marginTop="@dimen/common_6dp"
android:src="@drawable/shape_e5e5e8_r7"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/item_linear_layout"
android:layout_width="@dimen/common_210dp"
android:layout_height="@dimen/common_152dp"
android:layout_weight="1"
android:background="@color/transparent"
android:gravity="fill_horizontal"
android:paddingTop="@dimen/common_6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<NumberPicker
android:id="@+id/number_picker_left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.15"
android:descendantFocusability="blocksDescendants" />
<NumberPicker
android:id="@+id/number_picker_center"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.15"
android:descendantFocusability="blocksDescendants" />
<NumberPicker
android:id="@+id/number_picker_right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.15"
android:descendantFocusability="blocksDescendants" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
代码调用
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.NumberPicker;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.autel.cruiser.R;
import com.autel.lib.utils.ResourcesUtils;
import com.autel.util.log.AutelLog;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.Objects;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* <p> 功能描述:时间选择器
* <p>
* 详细描述:
*
* @Author: 龚寿生
* @CreateDate: 2021/8/30 14:46
* @UpdateUser: 最后一次更新者
* @UpdateDate: 2021/8/30 14:46
* @UpdateRemark: 最后一次更新说明
* @Version: 1.0 版本
*/
public class TimeDateView extends ConstraintLayout {
private static final int MIN_ZERO = 0;
private static final int MIN_ONE = 1;
private static final int HOUR_OF_DAY = 24;
private static final int MINUTE_OF_HOUR = 60;
private static final int SECOND_OF_MINUTE = 60;
private static final int YEAR_MAX = 5;
private static final int MONTH_OF_YEAR = 12;
private static final int DATE_MODE = 0;
private static final int TIME_MODE = 1;
@BindView(R.id.iv_bg)
ImageView iv_bg;
@BindView(R.id.number_picker_left)
NumberPicker numberPickerLeft;
@BindView(R.id.number_picker_center)
NumberPicker numberPickerCenter;
@BindView(R.id.number_picker_right)
NumberPicker numberPickerRight;
//日期或者时间
private int mode;
private int leftDate;
private int centerDate;
private int rightDate;
private Calendar calendar;
// public TimeDateView(@NonNull @NotNull Context context) {
// super(context);
// initView(context);
// }
public TimeDateView(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TimeDateView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TimeDateView);
mode = array.getInteger(R.styleable.TimeDateView_mode, 0);
array.recycle();
initView(context);
}
private void initView(Context context) {
View view = inflate(context, R.layout.layout_time_date_view, this);
ButterKnife.bind(this, view);
initData();
initColor();
}
private void initData() {
calendar = Calendar.getInstance();
numberPickerLeft.setWrapSelectorWheel(false);
numberPickerLeft.setOnValueChangedListener((picker, oldVal, newVal) -> {
leftDate = newVal;
if (mode == DATE_MODE) {
changeDataValue();
}
if (onValueChangedLister != null) {
onValueChangedLister.onValueChanged(leftDate, centerDate, rightDate);
}
});
numberPickerCenter.setWrapSelectorWheel(false);
numberPickerCenter.setOnValueChangedListener((picker, oldVal, newVal) -> {
centerDate = newVal;
if (onValueChangedLister != null) {
onValueChangedLister.onValueChanged(leftDate, centerDate, rightDate);
}
if (mode == DATE_MODE) {
changeDataValue();
}
});
numberPickerRight.setWrapSelectorWheel(false);
numberPickerRight.setOnValueChangedListener((picker, oldVal, newVal) -> {
rightDate = newVal;
if (onValueChangedLister != null) {
onValueChangedLister.onValueChanged(leftDate, centerDate, rightDate);
}
});
if (mode == DATE_MODE) {
initDateView();
} else {
initTimeView();
}
updateDate();
}
private void initTimeView() {
iv_bg.setImageResource(R.mipmap.bg_time_date_right);
//24小时制,限制小时数为0~23
String[] hour = new String[HOUR_OF_DAY];
for (int i = 0; i < hour.length; i++) {
hour[i] = i + ResourcesUtils.getString(R.string.unit_hour);
}
numberPickerLeft.setDisplayedValues(hour);
numberPickerLeft.setMinValue(MIN_ZERO);
numberPickerLeft.setMaxValue(hour.length - 1);
//限制分钟数为0~59
String[] minute = new String[MINUTE_OF_HOUR];
for (int i = 0; i < minute.length; i++) {
minute[i] = i + ResourcesUtils.getString(R.string.unit_minute);
}
numberPickerCenter.setDisplayedValues(minute);
numberPickerCenter.setMinValue(MIN_ZERO);
numberPickerCenter.setMaxValue(minute.length - 1);
//限制秒数为0~59
String[] sec = new String[SECOND_OF_MINUTE];
for (int i = 0; i < sec.length; i++) {
sec[i] = i + ResourcesUtils.getString(R.string.unit_second);
}
numberPickerRight.setDisplayedValues(sec);
numberPickerRight.setMinValue(MIN_ZERO);
numberPickerRight.setMaxValue(sec.length - 1);
//初始化时间位置
leftDate = calendar.get(Calendar.HOUR_OF_DAY);
centerDate = calendar.get(Calendar.MINUTE);
rightDate = calendar.get(Calendar.SECOND);
}
private void initDateView() {
iv_bg.setImageResource(R.mipmap.bg_time_date_left);
//限制年份范围为前后五年
int yearNow = calendar.get(Calendar.YEAR);
String[] year = new String[YEAR_MAX + 1];
for (int i = 0; i < year.length; i++) {
year[i] = (yearNow + i) + ResourcesUtils.getString(R.string.unit_year);
}
numberPickerLeft.setMinValue(yearNow);
numberPickerLeft.setMaxValue(yearNow + YEAR_MAX);
numberPickerLeft.setDisplayedValues(year);
//设置月份范围为1~12
String[] month = new String[MONTH_OF_YEAR];
for (int i = 1; i <= month.length; i++) {
month[i - 1] = i + ResourcesUtils.getString(R.string.unit_month);
}
numberPickerCenter.setMinValue(MIN_ONE);
numberPickerCenter.setMaxValue(MONTH_OF_YEAR);
numberPickerCenter.setDisplayedValues(month);
//设置日期
int dayMax = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
String[] day = new String[dayMax];
for (int i = 1; i <= day.length; i++) {
day[i - 1] = i + ResourcesUtils.getString(R.string.unit_day);
}
numberPickerRight.setMinValue(MIN_ONE);
numberPickerRight.setMaxValue(dayMax);
numberPickerRight.setDisplayedValues(day);
//初始化日期位置
leftDate = calendar.get(Calendar.YEAR);
centerDate = calendar.get(Calendar.MONTH);
rightDate = calendar.get(Calendar.DATE);
}
public void changeDataValue() {
String dateStr = String.format(Locale.CHINA, "%d-%d", leftDate, centerDate);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM", Locale.CHINA);
try {
calendar.setTime(Objects.requireNonNull(simpleDateFormat.parse(dateStr)));
} catch (ParseException e) {
e.printStackTrace();
}
//设置日期
int dayMax = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
AutelLog.e("gss", calendar.getTime() + "dayMax=" + dayMax);
String[] day = new String[dayMax];
for (int i = 1; i <= day.length; i++) {
day[i - 1] = i + ResourcesUtils.getString(R.string.unit_day);
}
numberPickerRight.setMaxValue(dayMax);
numberPickerRight.setDisplayedValues(day);
numberPickerRight.setValue(MIN_ONE);
}
public void updateTimeView() {
if (onValueChangedLister != null) {
onValueChangedLister.onValueChanged(leftDate, centerDate, rightDate);
}
}
public void updateTimeView(int leftDate, int centerDate, int rightDate) {
this.leftDate = leftDate;
this.centerDate = centerDate;
this.rightDate = rightDate;
updateDate();
}
private void updateDate() {
numberPickerLeft.setValue(rightDate);
numberPickerCenter.setValue(centerDate);
numberPickerRight.setValue(rightDate);
}
private void initColor() {
setNumberPickerDividerColor(numberPickerLeft);
setNumberPickerDividerColor(numberPickerCenter);
setNumberPickerDividerColor(numberPickerRight);
}
private void setNumberPickerDividerColor(NumberPicker numberPicker) {
Field[] pickerFields = NumberPicker.class.getDeclaredFields();
for (Field pf : pickerFields) {
if (pf.getName().equals("mSelectionDivider")) {
pf.setAccessible(true);
try {
//设置分割线的颜色值
pf.set(numberPicker, new ColorDrawable(ResourcesUtils.getColor(R.color.transparent)));
} catch (IllegalArgumentException | Resources.NotFoundException | IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
}
private OnValueChangedLister onValueChangedLister;
public void setOnValueChangedLister(OnValueChangedLister onValueChangedLister) {
this.onValueChangedLister = onValueChangedLister;
}
public interface OnValueChangedLister {
void onValueChanged(int leftDate, int centerDate, int rightDate);
}
}