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

    <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版本限制的


版本要求高,低版本不适用
//AS提示的错误信息
Call requires API level 26 (current min is 21): android.widget.DatePicker#setOnDateChangedListener less... 

解决办法:
选择年月日的DatePicker

 <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 <strong>starting from zero</strong>.
     * @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版本的限制,一些方法不能正常使用,但是不能排除有其他方法也能同样实现效果。不拘束于开发的条条框框,跳出固定思维终能解决问题!

每天进步一点点。。。(2019-07-01)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352