5

I want a date picker to show only Month and Year. I've customized the Date Picker to do so i.e., to remove 'day' field from the picker,but in Android Lollipop Am getting picker with Day, Month and Year. Following is my piece of code. Please help me to know the problem. Thanks in advance.

    try {
        Field f[] = mDatePicker.getClass().getDeclaredFields();
        for (Field field : f) {

            if (field.getName().equals("mDaySpinner") || field.getName().equals("mDayPicker")) {
                field.setAccessible(true);
                Object dayPicker = new Object();
                dayPicker = field.get(mDatePicker);
                ((View) dayPicker).setVisibility(View.GONE);
            }

        }
    } catch (SecurityException e) {
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    }
sravanalakshmi.sunkara
  • 1,161
  • 2
  • 13
  • 35
  • What is not working? Is the app crashing? If so, post the stacktrace. – Egor Neliuba Oct 20 '14 at 07:44
  • showing day also, which is not correct in my case. It should display only Month and year. Working properly till Kitkat. – sravanalakshmi.sunkara Oct 20 '14 at 08:51
  • 1
    IMHO accessing internals on the date picker class is bad practices. You depend on the fields in question having certain names; if the names change... I think you're better off implementing your own custom widget with two normal numeric spinners. – Laur Ivan Oct 21 '14 at 13:57
  • This will break on future OS updates. You should never use reflection to access private framework resources in an app that you plan to release publicly. – alanv Mar 22 '15 at 02:04

3 Answers3

10

Using reflection to find and hide UI elements is not really a great practice. In your case, it stopped working in lollipop because the mDaySpinner is now contained in an internal private static DatePickerSpinngerDelegate class within the DatePicker class.

I would recommend going through the view hierarchy to find and hide the day spinner element instead. I wrote the following code that works in lollipop:

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    int daySpinnerId = Resources.getSystem().getIdentifier("day", "id", "android");
    if (daySpinnerId != 0) {
        View daySpinner = datePicker.findViewById(daySpinnerId);
        if (daySpinner != null) {
            daySpinner.setVisibility(View.GONE);
        }
    }
}
Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
cse
  • 109
  • 1
  • 5
  • @alanv The code example in this answer is _not_ using reflection. In fact, this answer specifically advises against using reflection by saying it is not a great practice. Perhaps you intended your comment for the code example in the original question, which actually does use reflection. – cse Mar 22 '15 at 01:51
  • Yes, though this answer is still attempting to use framework-private resources. The day ID resource isn't public and therefore is not guaranteed to exist. This solution isn't guaranteed to work on future OS versions or even across different OEM-customized versions of Lollipop. – alanv Mar 22 '15 at 02:08
  • 1
    @cse,@Sivakumar,@Maulik.J how to use this mang with datepicker dialog fragment?? – Reprator Dec 21 '15 at 07:52
0

This is a basic example of a month picker, but can be easily adapted to pick also year and/or day (works also for older android versions):

public void initMonthPicker(){
dp_mes = (DatePicker) findViewById(R.id.dp_mes);

int year    = dp_mes.getYear();
int month   = dp_mes.getMonth();
int day     = dp_mes.getDayOfMonth();

dp_mes.init(year, month, day, new DatePicker.OnDateChangedListener() {
    @Override
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        month_i = monthOfYear + 1;
        Log.e("selected month:", Integer.toString(month_i));
     //Add whatever you need to handle Date changes
    }
});

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
    int daySpinnerId = Resources.getSystem().getIdentifier("day", "id", "android");
    if (daySpinnerId != 0)
    {
        View daySpinner = dp_mes.findViewById(daySpinnerId);
        if (daySpinner != null)
        {
            daySpinner.setVisibility(View.GONE);
        }
    }

    int monthSpinnerId = Resources.getSystem().getIdentifier("month", "id", "android");
    if (monthSpinnerId != 0)
    {
        View monthSpinner = dp_mes.findViewById(monthSpinnerId);
        if (monthSpinner != null)
        {
            monthSpinner.setVisibility(View.VISIBLE);
        }
    }

    int yearSpinnerId = Resources.getSystem().getIdentifier("year", "id", "android");
    if (yearSpinnerId != 0)
    {
        View yearSpinner = dp_mes.findViewById(yearSpinnerId);
        if (yearSpinner != null)
        {
            yearSpinner.setVisibility(View.GONE);
        }
    }
} else { //Older SDK versions
    Field f[] = dp_mes.getClass().getDeclaredFields();
    for (Field field : f)
    {
        if(field.getName().equals("mDayPicker") || field.getName().equals("mDaySpinner"))
        {
            field.setAccessible(true);
            Object dayPicker = null;
            try {
                dayPicker = field.get(dp_mes);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            ((View) dayPicker).setVisibility(View.GONE);
        }

        if(field.getName().equals("mMonthPicker") || field.getName().equals("mMonthSpinner"))
        {
            field.setAccessible(true);
            Object monthPicker = null;
            try {
                monthPicker = field.get(dp_mes);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            ((View) monthPicker).setVisibility(View.VISIBLE);
        }

        if(field.getName().equals("mYearPicker") || field.getName().equals("mYearSpinner"))
        {
            field.setAccessible(true);
            Object yearPicker = null;
            try {
                yearPicker = field.get(dp_mes);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            ((View) yearPicker).setVisibility(View.GONE);
        }
    }
}

}

Carlos Borau
  • 1,433
  • 1
  • 24
  • 34
0

Went ahead making a modified Date Picker called Simple Date picker ... have used the code similar to Date Picker just to show month and year

see https://github.com/resengupta/Month-Year-Date-Picker

SimpleDatePickerDialog.java class is responsible for showing the month and year number picker. SimpleDatePickerDelegate.java works to apply rules to the number pickers. SimpleDatePickerDialogFragment.java is a DialogFragment which wraps the alert dialog.

ReeSen
  • 75
  • 4