Диалоговое окно настраиваемого выбора даты в Android Lollipop

Я хочу, чтобы в средстве выбора даты отображались только месяц и год. Я настроил средство выбора даты для этого, т.е. чтобы удалить поле «день» из средства выбора, но в Android Lollipop Am получает средство выбора с днем, месяцем и годом. Ниже приведен мой фрагмент кода. Пожалуйста, помогите мне разобраться в проблеме. Заранее спасибо.

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

person sravanalakshmi.sunkara    schedule 20.10.2014    source источник
comment
Что не работает? Приложение вылетает? Если да, опубликуйте трассировку стека.   -  person Egor Neliuba    schedule 20.10.2014
comment
также показывает день, что в моем случае неверно. Он должен отображать только месяц и год. Работает нормально до Китката.   -  person sravanalakshmi.sunkara    schedule 20.10.2014
comment
IMHO доступ к внутренним элементам в классе выбора даты - плохая практика. Вы зависите от названий полей, о которых идет речь; если имена меняются ... Я думаю, вам лучше реализовать свой собственный виджет с двумя обычными числовыми прядильщиками.   -  person Laur Ivan    schedule 21.10.2014
comment
Это нарушит будущие обновления ОС. Никогда не следует использовать отражение для доступа к частным ресурсам фреймворка в приложении, которое вы планируете выпустить публично.   -  person alanv    schedule 22.03.2015


Ответы (3)


Использование отражения для поиска и скрытия элементов пользовательского интерфейса - не самая лучшая практика. В вашем случае он перестал работать в lollipop, потому что mDaySpinner теперь содержится во внутреннем частном статическом классе DatePickerSpinngerDelegate внутри класса DatePicker.

Я бы порекомендовал пройти через иерархию представлений, чтобы вместо этого найти и скрыть элемент прядильщика дня. Я написал следующий код, который работает в 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);
        }
    }
}
person cse    schedule 20.01.2015
comment
@alanv Пример кода в этом ответе не использует отражение. Фактически, этот ответ специально рекомендует не использовать отражение, говоря, что это не очень хорошая практика. Возможно, вы предназначаете свой комментарий для примера кода в исходном вопросе, который на самом деле использует отражение. - person cse; 22.03.2015
comment
Да, хотя этот ответ все еще пытается использовать частные ресурсы фреймворка. Ресурс идентификатора дня не является общедоступным, и поэтому его существование не гарантируется. Не гарантируется, что это решение будет работать в будущих версиях ОС или даже в различных версиях Lollipop, адаптированных для изготовителей оборудования. - person alanv; 22.03.2015
comment
@ cse, @ Sivakumar, @ Maulik.J как использовать этот ман с фрагментом диалогового окна datepicker ?? - person Reprator; 21.12.2015

Это базовый пример выбора месяца, но его можно легко адаптировать для выбора года и / или дня (работает также для более старых версий Android):

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

}

person Carlos Borau    schedule 02.10.2015

Продолжил создание модифицированного средства выбора даты под названием Простое средство выбора даты ... использовал код, аналогичный средству выбора даты, только для отображения месяца и года

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

Класс SimpleDatePickerDialog.java отвечает за отображение средства выбора номера месяца и года. SimpleDatePickerDelegate.java применяет правила к сборщикам чисел. SimpleDatePickerDialogFragment.java - это DialogFragment, который является оболочкой для диалогового окна предупреждения.

person ReeSen    schedule 15.10.2015