How to change DatePicker's CalendarView's

2019-04-13 09:21发布

问题:

I worked so hard to change the default background color of Lollipop's DatePicker. I cannot simply use Styleable attrs to change the default style. And as mentioned in another post, I can only use reflection to find the view, and then make changes on it.

e.g.

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    int monthDayYearLayoutId = Resources.getSystem().getIdentifier("date_picker_month_day_year_layout", "id", "android");
    if (monthDayYearLayoutId != 0) {
        View monthDayYearLayout = datePicker.findViewById(monthDayYearLayoutId);
        if (monthDayYearLayout != null) {
            monthDayYearLayout.setBackgroundColor(getResources().getColor(R.color.colorful));
        } 
    } 
} 

However, I am only able to access the upper half of the DatePicker (see below).

DatePicker's upper half

However,for the lower half which is a CalendarView (see below), I cannot change using the same approach, as I cannot find the view (I tried to find the view by the id R.id.calendar_view, yet it is not working.).

DatePicker's lower half

To be precise, I would like to change the background color of the circled date, and the textColor for the present date (in this case, it is 7th March, 2014)

Any hints? Thanks a lot.

Updates:

After looking through the docs, I found that the lower half's calendar is in fact a SimpleMonthView.class, and the background color of the circle and the textColor for the present day are both governed by the param (int) mSelectedDayColor.

    mSelectedDayColor = colors.getColorForState(ENABLED_SELECTED_STATE_SET,
            res.getColor(R.color.holo_blue_light));

I cannot use the previous method, since the calendar is created in the onDraw method programmatically, but not by inflating a layout file.

So the problem boils down to - how could I change the resource value for mSelectedDayColor?

Thanks..

Updates: After working on alanv's solution, I tried this: Since I am working on Lollipop's DatePicker, I put the following in v21-styles.xml:

<style name="MyCalendarView" parent="@android:style/Widget.CalendarView">
    <item name="android:showWeekNumber">true</item>
    <item name="android:minDate">01/01/2016</item>
    <item name="android:maxDate">12/31/2100</item>
    <item name="android:shownWeekCount">6</item>
    <item name="android:selectedWeekBackgroundColor">#330099FF</item>
    <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
    <item name="android:unfocusedMonthDateColor">#66FFFFFF</item>
    <item name="android:weekNumberColor">#33FFFFFF</item>
    <item name="android:weekSeparatorLineColor">#19FFFFFF</item>
</style>

And I changed some of the default values, eg. android:minDate.

And in my activity_main.xml,

<DatePicker
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/date_picker"
    android:layout_centerHorizontal="true"
    android:theme="@style/MyCalendarView"/>

But there is no effect on DatePicker for Lollipop.

回答1:

Any code using reflection may break on future OS updates. You should never use reflection to access private APIs or values.

The easiest way would be to create an overlay theme that redefines android:colorAccent and apply that to your DatePicker.

res/values/styles.xml:

<style name="MyThemeOverlay">
    <item name="android:colorAccent">@color/my_accent</item>
</style>

res/layout/my_layout.xml:

<DatePicker
    ...
    android:theme="@style/MyThemeOverlay" />