Скрыть день, месяц или год с DatePicker в Android 5.0+ Lollipop

Я искал решение скрыть любой из следующих прядильщиков из DatePicker. Для Android 5.0 внутренние переменные были изменены, и в моем случае спиннеры "День" и "Месяц" были снова видны после обновления на моем устройстве.

Android 4.4 и решение Kitkat

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

    // Initialize Date Picker
    int year    = dpDate.getYear();
    int month   = dpDate.getMonth();
    int day     = dpDate.getDayOfMonth();
    dpDate.init(year, month, day, this);

Field f[] = dpDate.getClass().getDeclaredFields();
            for (Field field : f) 
            {
                // Hides the DAY spinner
                if(field.getName().equals("mDayPicker") || field.getName().equals("mDaySpinner")) 
                {
                    field.setAccessible(true);
                    Object dayPicker = new Object();
                    dayPicker = field.get(dpDate);
                    ((View) dayPicker).setVisibility(View.GONE);
                }

                // Hides the MONTH spinner
                if(field.getName().equals("mMonthPicker") || field.getName().equals("mMonthSpinner")) 
                {
                    field.setAccessible(true);
                    Object monthPicker = new Object();
                    monthPicker = field.get(dpDate);
                    ((View) monthPicker).setVisibility(View.GONE);
                }

                // Hides the YEAR spinner
                if(field.getName().equals("mYearPicker") || field.getName().equals("mYearSpinner")) 
                {
                    field.setAccessible(true);
                    Object yearPicker = new Object();
                    yearPicker = field.get(dpDate);
                    ((View) myearPicker).setVisibility(View.GONE);
                }
            }

Android 5.0+ Lollipop Solution

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

    // Initialize Date Picker
    int year    = dpDate.getYear();
    int month   = dpDate.getMonth();
    int day     = dpDate.getDayOfMonth();
    dpDate.init(year, month, day, this);

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

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
            {
                int monthSpinnerId = Resources.getSystem().getIdentifier("month", "id", "android");
                if (monthSpinnerId != 0) 
                {
                    View monthSpinner = dpDate.findViewById(monthSpinnerId);
                    if (monthSpinner != null) 
                    {
                        monthSpinner.setVisibility(View.GONE);
                    }
                }
            }

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
            {
                int yearSpinnerId = Resources.getSystem().getIdentifier("year", "id", "android");
                if (yearSpinnerId != 0) 
                {
                    View yearSpinner = dpDate.findViewById(yearSpinnerId);
                    if (yearSpinner != null) 
                    {
                        yearSpinner.setVisibility(View.GONE);
                    }
                }
            }

Я нашел выше решение этой проблемы здесь: Диалоговое окно выбора даты в Android Lollipop

Я хотел убедиться, что он легко доступен для поиска, чтобы другие могли извлечь из этого выгоду, поэтому я создал этот новый пост. (Решение заняло у меня несколько часов, чтобы найти и понять, поэтому я надеюсь помочь кому-то в этом).

Я тестировал это, и он отлично работает. Фактически, если вы сначала поместите решение для Lollipop, а затем под этим, в коде, поставьте решение для Kitkat, тогда оно совместимо для обеих версий без помех. (Обязательно используйте try/catch;)

EDIT 7.22.2015: Я думал, что это было очевидно, если вы использовали DatePicker, чтобы его нужно было инициализировать. Я включил код, показывающий, что вам нужно инициализировать DatePicker, прежде чем запускать остальную часть кода (в обеих ситуациях), иначе ваши представления будут генерировать исключение NullPointerException. Это включает yearSpinner, бросающий нуль. Кроме того, у вас должно быть хотя бы одно представление для даты, не скрывайте все 3, т.е. Не скрывайте день, месяц и год одновременно.

Ответ 1

Просто для ленивых костей, это полностью интегрированный код (любой SDK), который работает для меня, чтобы построить сборщик месяцев (90%, равный предложению @Brandon):

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);
            }
        }
    }
}

Ответ 2

Очень простой, но не интуитивный.

Сначала измените тему с DialogPicker

new DatePickerDialog(getActivity(),android.R.style.Theme_Holo_Dialog, this, year,month, day);

Теперь да, вы можете скрыть любой счетчик.

dialog.getDatePicker().findViewById(getResources().getIdentifier("day","id","android")).setVisibility(View.GONE);

Прекрасно работает для меня в 5.0.2 API 21