前言:目前随着Android系统得完善,对UI界面要求也相应增高,对于Android自带得时间选择框界面过丑,自定义封装一个与IOS一致的三级联动时间框。
首先看看效果:
首先介绍一下控件的主要构成
1、PickerView,滚动的View
2、MyDateTimePickDialog 自己定义的时间框dialog,用于处理逻辑
3、xml与资源文件布局
下面看下代码
xml布局的使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="#f2f2f2">
<TextView
android:id="@+id/cancel_my_date_time_pick_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="取消"
android:textColor="#f74948"/>
<TextView
android:id="@+id/ok_my_date_time_pick_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="确定"
android:textColor="#f74948" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:orientation="horizontal"
android:background="#fff">
<com.example.timeapplication.timeview.PickerView
android:id="@+id/myPickerView_my_date_time_pick_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.example.timeapplication.timeview.PickerView
android:id="@+id/myPickerView_my_date_time_pick_view1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.example.timeapplication.timeview.PickerView
android:id="@+id/myPickerView_my_date_time_pick_view2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.example.timeapplication.timeview.PickerView
android:id="@+id/myPickerView_my_date_time_pick_view3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.example.timeapplication.timeview.PickerView
android:id="@+id/myPickerView_my_date_time_pick_view4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.example.timeapplication.timeview.PickerView
android:id="@+id/myPickerView_my_date_time_pick_view5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000" />
</LinearLayout>
此处放六个PickerView,可以自己方便滑动,分别是年月日,时分秒控件
MyDateTimePickDialog的介绍
1、构造方法
在构造方法里实现年月日的初始化,控件显示的位置与动画的初始化,和按钮的监听事件
public MyDateTimePickDialog(Context context) {
super(context);
mContext = context;
View view = LayoutInflater.from(mContext).inflate(R.layout.layout_my_date_time_pick_view, null);
setContentView(view);
Window window = this.getWindow();
window.setGravity(Gravity.BOTTOM);
window.setBackgroundDrawableResource(R.drawable.shape_my_bottom_dialog);
window.setWindowAnimations(R.style.dialog_anim);
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(params);
TextView tvCancel = view.findViewById(R.id.cancel_my_date_time_pick_view);
TextView tvOk = view.findViewById(R.id.ok_my_date_time_pick_view);
mPickViewYear = view.findViewById(R.id.myPickerView_my_date_time_pick_view);
mPickViewMonth = view.findViewById(R.id.myPickerView_my_date_time_pick_view1);
mPickViewDay = view.findViewById(R.id.myPickerView_my_date_time_pick_view2);
mPickViewHour = view.findViewById(R.id.myPickerView_my_date_time_pick_view3);
mPickViewMinute = view.findViewById(R.id.myPickerView_my_date_time_pick_view4);
mPickViewSecond = view.findViewById(R.id.myPickerView_my_date_time_pick_view5);
mCalendar = Calendar.getInstance();
mYear = mCalendar.get(Calendar.YEAR);
mMonth = mCalendar.get(Calendar.MONTH) + 1; // 获取的 月 从 0 开始
mDay = mCalendar.get(Calendar.DAY_OF_MONTH);
mHour = mCalendar.get(Calendar.HOUR_OF_DAY);
mMinute = mCalendar.get(Calendar.MINUTE);
mSecond = mCalendar.get(Calendar.SECOND);
tvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mCancelListener != null)
mCancelListener.cancel();
}
});
tvOk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mYearStr = mYear + "";
mMonthStr = formatTime(mMonth);
mDayStr = formatTime(mDay);
mHourStr = formatTime(mHour);
mMinuteStr = formatTime(mMinute);
mSecondStr = formatTime(mSecond);
if (mOkListener != null)
mOkListener.ok(mYearStr, mMonthStr, mDayStr, mHourStr, mMinuteStr, mSecondStr);
}
});
}
2、对年月日时分秒逻辑封装
private void initPickView() {
// ============= 年 数据 =============
if (mType != 2) {
List<String> listYear = new ArrayList<>();
int index = 0;
for (int i = 0; i < 20; i++) {
String year = (mCalendar.get(Calendar.YEAR) - 10 + i) + "年";
listYear.add(year);
if (year.equals(mYear + "年"))
index = i;
}
mPickViewYear.setData(listYear, false);
mPickViewYear.setSelected(index);
mPickViewYear.setOnSelectListener(new PickerView.onSelectListener() {
@Override
public void onSelect(String text) {
String yearStr = text.replace("年", "");
if (yearStr.matches("[0-9]+"))
mYear = Integer.parseInt(yearStr);
setDayData();
}
});
}
// =============== 设置 日 数据 =================
if (mType != 2)
setDayData();
// ==================== 设置 月 数据 ======================
if (mType != 2) {
List<String> listMonth = new ArrayList<>();
for (int j = 1; j <= 12; j++) {
if (j < 10)
listMonth.add("0" + j + "月");
else
listMonth.add(j + "月");
}
mPickViewMonth.setData(listMonth);
mPickViewMonth.setSelected(mMonth - 1);
mPickViewMonth.setOnSelectListener(new PickerView.onSelectListener() {
@Override
public void onSelect(String text) {
String monthStr = text.replace("月", "");
if (monthStr.matches("[0-9]+"))
mMonth = Integer.parseInt(monthStr);
setDayData();
}
});
}
// ================= 设置 时 数据 ====================
if (mType != 1) {
List<String> listHour = new ArrayList<>();
for (int i = 0; i <= 23; i++) {
if (i < 10) {
listHour.add("0" + i + "时");
} else
listHour.add(i + "时");
}
mPickViewHour.setData(listHour);
mPickViewHour.setSelected(mHour);
mPickViewHour.setOnSelectListener(new PickerView.onSelectListener() {
@Override
public void onSelect(String text) {
String hourStr = text.replace("时", "");
if (hourStr.matches("[0-9]+"))
mHour = Integer.parseInt(hourStr);
}
});
}
// ================ 设置 分 数据 =================
if (mType != 1) {
List<String> listMinute = new ArrayList<>();
for (int i = 0; i <= 59; i++) {
if (i < 10)
listMinute.add("0" + i + "分");
else
listMinute.add(i + "分");
}
mPickViewMinute.setData(listMinute);
mPickViewMinute.setSelected(mMinute);
mPickViewMinute.setOnSelectListener(new PickerView.onSelectListener() {
@Override
public void onSelect(String text) {
String minuteStr = text.replace("分", "");
if (minuteStr.matches("[0-9]+"))
mMinute = Integer.parseInt(minuteStr);
}
});
}
// ================ 设置 秒 数据 ==================
if (mType != 1 && mType != 2) {
List<String> listSecond = new ArrayList<>();
for (int i = 0; i <= 59; i++) {
if (i < 10)
listSecond.add("0" + i + "秒");
else
listSecond.add(i + "秒");
}
mPickViewSecond.setData(listSecond);
mPickViewSecond.setSelected(mSecond);
mPickViewSecond.setOnSelectListener(new PickerView.onSelectListener() {
@Override
public void onSelect(String text) {
String secondStr = text.replace("秒", "");
if (secondStr.matches("[0-9]+"))
mSecond = Integer.parseInt(secondStr);
}
});
}
}
// 设置 日 数据
private void setDayData() {
List<String> listDay = new ArrayList<>();
int dayNum = 31;
if (mMonth == 4 || mMonth == 6 || mMonth == 9 || mMonth == 11) {
dayNum = 30;
}
if (mMonth == 2) {
if (mYear % 400 == 0 || mYear % 4 == 0) { // 闰年
dayNum = 29;
} else {
dayNum = 28;
}
}
for (int i = 1; i <= dayNum; i++) {
if (i < 10)
listDay.add("0" + i + "日");
else
listDay.add(i + "日");
}
mPickViewDay.setData(listDay);
mPickViewDay.setSelected(mDay - 1);
mPickViewDay.setOnSelectListener(new PickerView.onSelectListener() {
@Override
public void onSelect(String text) {
String dayStr = text.replace("日", "");
if (dayStr.matches("[0-9]+"))
mDay = Integer.parseInt(dayStr);
}
});
}
3、只显示年月日,或者时分秒
public void setType(int type){
mType = type;
if (mType == 1) { // 只筛选 年月日,把 时分秒 控件 隐掉
mPickViewHour.setVisibility(View.GONE);
mPickViewMinute.setVisibility(View.GONE);
mPickViewSecond.setVisibility(View.GONE);
}
if (mType == 2) { // 只筛选 时分,把 年月日 秒 控件隐掉
mPickViewYear.setVisibility(View.GONE);
mPickViewMonth.setVisibility(View.GONE);
mPickViewDay.setVisibility(View.GONE);
mPickViewSecond.setVisibility(View.GONE);
}
}
控件的使用
使用上非常简单,直接按封装好的使用即可,看代码
public void setStartEndTime() {
if (mPickDialog == null)
mPickDialog = new MyDateTimePickDialog(MainActivity.this);
// 此处设置一个默认值
int[] startDateAndTime = TimeUtils.getDateAndTime("2022-7-19 13:23:44");
if (startDateAndTime.length == 6) {
mPickDialog.setDateAndTime(startDateAndTime[0], startDateAndTime[1], startDateAndTime[2], startDateAndTime[3], startDateAndTime[4], startDateAndTime[5]);
}
mPickDialog.showThisDialog(new MyDateTimePickDialog.OnPickViewOkListener() {
@Override
public void ok(String year, String month, String date, String hour, String minute, String second) {
Log.i("xjz111",year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second);
mPickDialog.dismiss();
}
}, new MyDateTimePickDialog.OnPickViewCancelListener() {
@Override
public void cancel() {
mPickDialog.dismiss();
}
});
}
其中,ok的回调就是选择了之后,得到的时间数据,再进行逻辑封装处理即可。