android datepicker 不显示日历,Android DatePicker遇到的那些坑

前言

最近遇到一个项目,需要用到时间选择器,之前图简单,直接沿用了同事的wheelView,把可选的时间以列表的形式加载到wheelView,实现xxxx年xx月是不成问题的, 但是当我们要选择xxxx年xx月xx日时就麻烦了,月有大小月之分,年有平年闰年之分,对于每月有几天的计算还是麻烦的,所以决定弃用wheelView,用Android自带的DatePicker,在选择日期上简单方便。

接下来,进入正题,DatePicker如何自定义,如何私人定制为项目需求所用?

1.DatePicker只显示年月的选择

参考文章:https://www.cnblogs.com/ivan-aldrich/p/4227439.html

在网上找了一顿资料,终于实现了隐藏DatePicker中day的显示,通过反射的方法改变DatePicker的显示

来看代码:

选择年月的DatePicker

android:id="@+id/datePicker4YM"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:calendarViewShown="false" //是否显示日历视图

android:datePickerMode="spinner" //显示为spinner视图

android:spinnersShown="true" /> //是否显示为上下滑动样式

通过反射隐藏控件中的day

/**

* 隐藏时间控件中的日期选择,只显示控件中的年、月

*

* @param mDatePicker

*/

private static void hideDay(DatePicker mDatePicker) {

try {

/* 处理android5.0以上的特殊情况 */

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

int daySpinnerId = Resources.getSystem().getIdentifier("day", "id", "android");

if (daySpinnerId != 0) {

View daySpinner = mDatePicker.findViewById(daySpinnerId);

if (daySpinner != null) {

daySpinner.setVisibility(View.GONE);

}

}

} else {

Field[] datePickerfFields = mDatePicker.getClass().getDeclaredFields();

for (Field datePickerField : datePickerfFields) {

if ("mDaySpinner".equals(datePickerField.getName()) || ("mDayPicker").equals(datePickerField.getName())) {

datePickerField.setAccessible(true);

Object dayPicker = new Object();

try {

dayPicker = datePickerField.get(mDatePicker);

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

}

((View) dayPicker).setVisibility(View.GONE);

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

调用

DatePicker datePicker4YM = findViewById(R.id.datePicker4YM);

hideDay(datePicker4YM); //按月选择,控件隐藏日期的显示

**需要注意的是,在4.0以前,DatePicker中控件的名字是mDayPicker/mMonthPicker/mYearPicker。

在4.0之后才改成了mDayspinner/mMonthSpinner/mYearSpinner.**

2.设置OnDateChangedListener事件

用过DatePicker的同学都知道,DatePicker是可以直接调用自己方法OnDateChangedListener,但是和DatePickerDialog不同的是,DatePicker直接调用自己方法OnDateChangedListener是有Android版本限制的

425d6e46db53

版本要求高,低版本不适用

//AS提示的错误信息

Call requires API level 26 (current min is 21): android.widget.DatePicker#setOnDateChangedListener less...

解决办法:

选择年月日的DatePicker

android:id="@+id/datePicker4Day"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:calendarViewShown="false" />

设置OnDateChangedListener事件

int year = calendar.get(Calendar.YEAR);

int month = calendar.get(Calendar.MONTH);

int day = calendar.get(Calendar.DAY_OF_MONTH);

DatePicker datePicker4Day = findViewById(R.id.datePicker4Day);

datePicker4Day.init(year, month, day, new DatePicker.OnDateChangedListener() {

@Override

public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {

monthOfYear = monthOfYear + 1;

String selectedDay = year + "-" + (monthOfYear < 10 ? "0" + monthOfYear : monthOfYear) + "-"

+ (dayOfMonth < 10 ? "0" + dayOfMonth : dayOfMonth);

Log.i("onDateChanged", selectedDay);

}

});

DatePicker设置OnDateChangedListener事件需要通过

/**

* Initialize the state. If the provided values designate an inconsistent

* date the values are normalized before updating the spinners.

*

* @param year The initial year.

* @param monthOfYear The initial month starting from zero.

* @param dayOfMonth The initial day of the month.

* @param onDateChangedListener How user is notified date is changed by

* user, can be null.

*/

public void init(int year, int monthOfYear, int dayOfMonth,

OnDateChangedListener onDateChangedListener) {

mDelegate.init(year, monthOfYear, dayOfMonth, onDateChangedListener);

}

方法设置,传入时间选择器的默认年月日,这样的设置方法同样适用于上面的隐藏日选择的DatePicker。

总结

有些原生控件已经足够强大,可以满足项目需求,但是由于控件的强大,需要在原来基础上改动,于是用到反射原理巧妙地修改控件的配置。还有因为Android版本的限制,一些方法不能正常使用,但是不能排除有其他方法也能同样实现效果。不拘束于开发的条条框框,跳出固定思维终能解决问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值