DatePicker showing only year and month

Please indicate the source for reprinting: http://renyuan-1991.iteye.com/blogs/2304484 Let’s take a
look at the renderings first:

1. DatePicker that does not display the number of days
2. Set the display date range of DatePicker 3.
Style
adjustment of DatePicker Specific code:
To achieve this effect, first hide the Number in the last column (the three columns of DatePicker are all implemented with numbers). There are two ways to hide the last column, as follows:
    The first:
   
DatePicker dp = findDatePicker((ViewGroup) datePickerDialog.getWindow().getDecorView());
        if (dp != null) {
            ((ViewGroup)((ViewGroup) dp.getChildAt(0)).getChildAt(0)).getChildAt(2).setVisibility(View.GONE);
        }
    }
private DatePicker findDatePicker(ViewGroup group) {
    if (group != null) {
        for (int i = 0, j = group.getChildCount(); i < j; i++) {
            View child = group.getChildAt(i);
            if (child instanceof DatePicker) {
                return (DatePicker) child;
            } else if (child instanceof ViewGroup) {
                DatePicker result = findDatePicker((ViewGroup) child);
                if (result != null)
                    return result;
            }
        }
    }
    return null;
}
    

This method is used in DatePickerDialog, get the DatePicker through the findDatePicker method, and then get the number that displays the number of days according to the layout level of the DatePicker and set it to GONE. If we add the DatePicker to the layout by ourselves, we can directly get the number of the displayed days through the getChildAt method of DatePicker and set it to not display. In this example, it is set by the following method:
layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="180dp"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="5dip"
    android:paddingTop="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_marginBottom="-15dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Select month" />

    <DatePicker
        android:theme="@android:style/Theme.Holo.Light"
        android:id="@+id/datePickerStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:calendarViewShown="false" />
    <Button
        android:id="@+id/dd_btn_sure"
        android:layout_width="match_parent"
        android:layout_marginTop="-20dp"
        android:text="OK"
        android:textSize="18sp"
        android:background="@android:color/transparent"
        android:layout_height="wrap_content" />
</LinearLayout>

If the layout file is like the above, we can directly find the viewbyid in the logic code to get the DatePicker, and then call the following method to hide the control of the number of days.
.getChildAt(0)).getChildAt(0)).getChildAt(2).setVisibility(View.GONE);

Complete logic code:
public class MyChooseMonthDialog extends AlertDialog implements OnDateChangedListener, View.OnClickListener {
    private static final String YEAR = "YEAR";
    private static final String MONTH = "MONTH";
    private static final String DAY = "DAY";

    private final DatePicker mDatePicker;
    private final MyChooseMonthDialog.OnDateSetListener mCallBack;


    /**
     * The callback used to indicate the user is done filling in the date.
     */
    public interface OnDateSetListener {
        void onDateSet(DatePicker startDatePicker, int startYear, int startMonthOfYear, int startDayOfMonth);
    }

    /**
     * @param context     The context the dialog is to run in.
     * @param callBack    How the parent is notified that the date is set.
     * @param year        The initial year of the dialog.
     * @param monthOfYear The initial month of the dialog.
     * @param dayOfMonth  The initial day of the dialog.
     */
    public MyChooseMonthDialog(Context context, MyChooseMonthDialog.OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
        this(context, 0, callBack, year, monthOfYear, dayOfMonth);
    }

    public MyChooseMonthDialog(Context context, int theme, MyChooseMonthDialog.OnDateSetListener callBack, int year, int monthOfYear,
                               int dayOfMonth) {
        this(context, 0, callBack, year, monthOfYear, dayOfMonth, true);
    }

    /**
     * @param context     The context the dialog is to run in.
     * @param theme       the theme to apply to this dialog
     * @param callBack    How the parent is notified that the date is set.
     * @param year        The initial year of the dialog.
     * @param monthOfYear The initial month of the dialog.
     * @param dayOfMonth  The initial day of the dialog.
     */
    public MyChooseMonthDialog(Context context, int theme, MyChooseMonthDialog.OnDateSetListener callBack, int year, int monthOfYear,
                               int dayOfMonth, boolean isDayVisible) {
        super(context, theme);
        mCallBack = callBack;
        Context themeContext = getContext();
        setIcon (0);
        LayoutInflater inflater = (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.datepicker_dialog, null);
        Button dd_btn_sure = (Button) view.findViewById(R.id.dd_btn_sure);
        dd_btn_sure.setOnClickListener(this);
        setView(view);
        mDatePicker = (DatePicker) view.findViewById(R.id.datePickerStart);
        mDatePicker.init(year, monthOfYear, dayOfMonth, this);
        mDatePicker.setMaxDate(System.currentTimeMillis());
        setMyStyle(mDatePicker);
        // If you want to hide the current date, use the following method.
        if (!isDayVisible) {
            hidDay(mDatePicker);
        }
    }

    private void setMyStyle(DatePicker mDatePicker) {
        LinearLayout llFirst = (LinearLayout) mDatePicker.getChildAt(0);
        LinearLayout llSecond = (LinearLayout) llFirst.getChildAt(0);
        llSecond.setPadding(0, 0,0, 0);
        llSecond.setBackgroundResource(R.color.transparent);//Set the background of datepickerdialog

        for (int i = 0; i < llSecond.getChildCount(); i++) {
            NumberPicker picker = (NumberPicker) llSecond.getChildAt(i); // Numberpickers in llSecond
            Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                //change the color of the dividing line
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        pf.set(picker, ContextCompat.getDrawable(YztApplication.getInstance(), R.color.investor_ilp_red));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace ();
                    }
                    break;
                }
            }
        }
    }

    private void hidDay(DatePicker mDatePicker) {
        if(mDatePicker!=null){
            ((ViewGroup)((ViewGroup) mDatePicker.getChildAt(0)).getChildAt(0)).getChildAt(2).setVisibility(View.GONE);
        }
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.dd_btn_sure:
                tryNotifyDateSet();
                this.dismiss();
                break;
        }
    }

    @Override
    public void onDateChanged(DatePicker view, int year, int month, int day) {
        if (view.getId() == R.id.datePickerStart)
            mDatePicker.init(year, month, day, this);
        // updateTitle(year, month, day);
    }

    /**
     * Get the DatePicker of the start date
     *
     * @return The calendar view.
     */
    public DatePicker getDatePickerStart() {
        return mDatePicker;
    }

    /**
     * Sets the start date.
     *
     * @param year        The date year.
     * @param monthOfYear The date month.
     * @param dayOfMonth  The date day of month.
     */
    public void updateStartDate(int year, int monthOfYear, int dayOfMonth) {
        mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
    }


    private void tryNotifyDateSet() {
        if (mCallBack != null) {
            mDatePicker.clearFocus();
            mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(), mDatePicker.getMonth(),
                    mDatePicker.getDayOfMonth());
        }
    }

    @Override
    protected void onStop() {
        // tryNotifyDateSet();
        super.onStop();
    }

    @Override
    public Bundle onSaveInstanceState() {
        Bundle state = super.onSaveInstanceState();
        state.putInt(YEAR, mDatePicker.getYear());
        state.putInt(MONTH, mDatePicker.getMonth());
        state.putInt(DAY, mDatePicker.getDayOfMonth());
        return state;
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState (savedInstanceState);
        int year = savedInstanceState.getInt(YEAR);
        int month = savedInstanceState.getInt(MONTH);
        int day = savedInstanceState.getInt(DAY);
        mDatePicker.init(year,month,day, this);
    }
}

The most important of which is the following code:
private void setMyStyle(DatePicker mDatePicker) {
        LinearLayout llFirst = (LinearLayout) mDatePicker.getChildAt(0);
        LinearLayout llSecond = (LinearLayout) llFirst.getChildAt(0);
        llSecond.setPadding(0, 0,0, 0);
        llSecond.setBackgroundResource(R.color.transparent);//Set the background of datepickerdialog

        for (int i = 0; i < llSecond.getChildCount(); i++) {
            NumberPicker picker = (NumberPicker) llSecond.getChildAt(i); // Numberpickers in llSecond
            Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                //change the color of the dividing line
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        pf.set(picker, ContextCompat.getDrawable(YztApplication.getInstance(), R.color.investor_ilp_red));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace ();
                    }
                    break;
                }
            }
        }
    }

This code gets his sub-layout through DatePicker, then gets the dividing line in NumberPicker through reflection, and modifies its color. In the same way, we can also get the column showing the number of days through reflection and set it to be hidden. This is the second method. The code is as follows:
private void hidDay(DatePicker mDatePicker) {
         Field[] datePickerfFields = mDatePicker.getClass().getDeclaredFields();
         for (Field datePickerField : datePickerfFields) {
             if ("mDaySpinner".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 ();
                 }
                 // datePicker.getCalendarView().setVisibility(View.GONE);
                 ((View) dayPicker).setVisibility(View.GONE);
             }
         }
     }

The code of the second method above comes from: http://www.cnblogs.com/jilianggqq/p/4139510.html
After 5.0, the system test failed, and the theme of setting holo is not enough. I took a look and the reason is because DatePickerDialog The layout level in the source code does not correspond to the logic reflected in the logic code. A slight modification should be able to achieve the same effect.
    When the last column is hidden, the AlertDialog does not adjust the size of the layout. At this time, it looks very inconsistent. We need to call the setLayout method after calling the show in the Dialog. Note that it must be called after the show. The code is as follows:
datePickerDialog.show();
        datePickerDialog.getWindow().setLayout(Utils.dip2px(IncomeDetailActivity.this,260),Utils.dip2px(IncomeDetailActivity.this,300));

Set DatePicker's date range:
mDatePicker.setMaxDate(System.currentTimeMillis());

There is a small problem after setting the date range. When the month displayed by DatePicker is the current month, you can see the next month. In theory, if the date range is set to today, the next month will not be displayed. When I saw the month display, it immediately returned to normal. That is to say, after mDatePicker.setMaxDate, the display of the year but not the month is refreshed.... The specific reason remains to be studied.
I hope that programming-loving friends can join this group, help each other, and learn together. Group number: 141877583

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326684526&siteId=291194637