1bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/* 2bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Copyright (C) 2014 The Android Open Source Project 3bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * 4bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 5bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * you may not use this file except in compliance with the License. 6bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * You may obtain a copy of the License at 7bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * 8bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 9bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * 10bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 11bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 12bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * See the License for the specific language governing permissions and 14bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * limitations under the License. 15bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 16bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 17bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Megliopackage android.widget; 18bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.annotation.Nullable; 20bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.Context; 21bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.ColorStateList; 22bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.Configuration; 23bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.Resources; 24bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.TypedArray; 25ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viveretteimport android.icu.text.DateFormat; 26c3e5a82691ac9094189a000430eab939e9020b2bAlan Viveretteimport android.icu.text.DisplayContext; 2768763be41cffbcb4883a0a6293fc1aa9e17a3957Alan Viveretteimport android.icu.util.Calendar; 28bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.os.Parcelable; 29bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.util.AttributeSet; 300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.StateSet; 31bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.HapticFeedbackConstants; 32bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.LayoutInflater; 33bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.View; 340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.View.OnClickListener; 350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.ViewGroup; 36bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.accessibility.AccessibilityEvent; 370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.DayPickerView.OnDaySelectedListener; 380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.YearPickerView.OnYearSelectedListener; 39bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 4099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.R; 4199441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 42bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Locale; 43bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 44bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/** 45bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * A delegate for picking up a date (day / month / year). 46bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteclass DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { 480a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette private static final int USE_LOCALE = 0; 49bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 50bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int UNINITIALIZED = -1; 510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private static final int VIEW_MONTH_DAY = 0; 520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private static final int VIEW_YEAR = 1; 53bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 54bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int DEFAULT_START_YEAR = 1900; 55bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int DEFAULT_END_YEAR = 2100; 56bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 57bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int ANIMATION_DURATION = 300; 58bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 5960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette private static final int[] ATTRS_TEXT_COLOR = new int[] { 6060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette com.android.internal.R.attr.textColor}; 6160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette private static final int[] ATTRS_DISABLED_ALPHA = new int[] { 620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette com.android.internal.R.attr.disabledAlpha}; 63bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 64ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette private DateFormat mYearFormat; 65ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette private DateFormat mMonthDayFormat; 667119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Top-level container. 680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private ViewGroup mContainer; 697119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Header views. 710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private TextView mHeaderYear; 720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private TextView mHeaderMonthDay; 737119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Picker views. 750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private ViewAnimator mAnimator; 76bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private DayPickerView mDayPickerView; 77bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private YearPickerView mYearPickerView; 78bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 79bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio // Accessibility strings. 80bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private String mSelectDay; 81bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private String mSelectYear; 82bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 83bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private int mCurrentView = UNINITIALIZED; 84bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 85452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mTempDate; 86452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mMinDate; 87452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mMaxDate; 88bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 890a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette private int mFirstDayOfWeek = USE_LOCALE; 900a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette 913053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs, 92bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio int defStyleAttr, int defStyleRes) { 93bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio super(delegator, context); 94bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final Locale locale = mCurrentLocale; 96452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mCurrentDate = Calendar.getInstance(locale); 97452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mTempDate = Calendar.getInstance(locale); 98452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mMinDate = Calendar.getInstance(locale); 99452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mMaxDate = Calendar.getInstance(locale); 100bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 10149e6c4adbfad8cac28a0c7c68918b443a64a07d8You Kim mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1); 10249e6c4adbfad8cac28a0c7c68918b443a64a07d8You Kim mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31); 103bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 10460727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final Resources res = mDelegator.getResources(); 105bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final TypedArray a = mContext.obtainStyledAttributes(attrs, 106bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio R.styleable.DatePicker, defStyleAttr, defStyleRes); 107bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 108bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio Context.LAYOUT_INFLATER_SERVICE); 109bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int layoutResourceId = a.getResourceId( 1100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.DatePicker_internalLayout, R.layout.date_picker_material); 1110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up and attach container. 113f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator, false); 11443da25c6707b7ddd118bf507865d21cebc4ae70bAdam Powell mContainer.setSaveFromParentEnabled(false); 115f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mDelegator.addView(mContainer); 116bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up header views. 1188e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette final ViewGroup header = mContainer.findViewById(R.id.date_picker_header); 1198e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette mHeaderYear = header.findViewById(R.id.date_picker_header_year); 1200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setOnClickListener(mOnHeaderClickListener); 1218e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date); 1220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener); 123ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette 1240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // For the sake of backwards compatibility, attempt to extract the text 1250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // color from the header month text appearance. If it's set, we'll let 1260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // that override the "real" header text color. 1270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette ColorStateList headerTextColor = null; 128bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @SuppressWarnings("deprecation") 1300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int monthHeaderTextAppearance = a.getResourceId( 1314e5168fae43e783a35c5bc731e500196005268fbAlan Viverette R.styleable.DatePicker_headerMonthTextAppearance, 0); 1320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (monthHeaderTextAppearance != 0) { 1330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TypedArray textAppearance = mContext.obtainStyledAttributes(null, 1340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette ATTRS_TEXT_COLOR, 0, monthHeaderTextAppearance); 1350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final ColorStateList legacyHeaderTextColor = textAppearance.getColorStateList(0); 1360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette headerTextColor = applyLegacyColorFixes(legacyHeaderTextColor); 1370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette textAppearance.recycle(); 138bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 13960727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette 1400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (headerTextColor == null) { 1410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette headerTextColor = a.getColorStateList(R.styleable.DatePicker_headerTextColor); 14260727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette } 14360727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette 1440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (headerTextColor != null) { 1450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setTextColor(headerTextColor); 1460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setTextColor(headerTextColor); 14760727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette } 148bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up header background, if available. 1500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (a.hasValueOrEmpty(R.styleable.DatePicker_headerBackground)) { 1510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette header.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground)); 1520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 15460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette a.recycle(); 15560b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette 1560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up picker container. 1578e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette mAnimator = mContainer.findViewById(R.id.animator); 1580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up day picker view. 1608e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker); 161e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek); 1624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMinDate(mMinDate.getTimeInMillis()); 1634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis()); 1644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setDate(mCurrentDate.getTimeInMillis()); 165e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener); 16650eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 1670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up year picker view. 1688e1a72964517bfd01d8e650453ef41e22f770f21Alan Viverette mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker); 1692a90fa6d94b7d31e997493d2d0601e5129ec7c3eAlan Viverette mYearPickerView.setRange(mMinDate, mMaxDate); 170e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR)); 1710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener); 1724e5168fae43e783a35c5bc731e500196005268fbAlan Viverette 1730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up content descriptions. 174bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mSelectDay = res.getString(R.string.select_day); 175bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mSelectYear = res.getString(R.string.select_year); 176bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Initialize for current locale. This also initializes the date, so no 1780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // need to call onDateChanged. 1790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onLocaleChanged(mCurrentLocale); 1800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentView(VIEW_MONTH_DAY); 1820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 1850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * The legacy text color might have been poorly defined. Ensures that it 1860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * has an appropriate activated state, using the selected state if one 1870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * exists or modifying the default text color otherwise. 1880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * 1890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param color a legacy text color, or {@code null} 1900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @return a color state list with an appropriate activated state, or 1910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * {@code null} if a valid activated state could not be generated 1920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 1930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Nullable 1940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private ColorStateList applyLegacyColorFixes(@Nullable ColorStateList color) { 1950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (color == null || color.hasState(R.attr.state_activated)) { 1960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return color; 1970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int activatedColor; 2000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int defaultColor; 2010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (color.hasState(R.attr.state_selected)) { 2020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette activatedColor = color.getColorForState(StateSet.get( 2030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_SELECTED), 0); 2040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette defaultColor = color.getColorForState(StateSet.get( 2050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette StateSet.VIEW_STATE_ENABLED), 0); 2060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } else { 2070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette activatedColor = color.getDefaultColor(); 2080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Generate a non-activated color using the disabled alpha. 2100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TypedArray ta = mContext.obtainStyledAttributes(ATTRS_DISABLED_ALPHA); 2110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final float disabledAlpha = ta.getFloat(0, 0.30f); 2120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette defaultColor = multiplyAlphaComponent(activatedColor, disabledAlpha); 2130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2147119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 2150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (activatedColor == 0 || defaultColor == 0) { 2160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // We somehow failed to obtain the colors. 2170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return null; 2180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2197119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 2200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int[][] stateSet = new int[][] {{ R.attr.state_activated }, {}}; 2210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int[] colors = new int[] { activatedColor, defaultColor }; 2220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return new ColorStateList(stateSet, colors); 2230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 224bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 2250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private int multiplyAlphaComponent(int color, float alphaMod) { 2260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int srcRgb = color & 0xFFFFFF; 2270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int srcAlpha = (color >> 24) & 0xFF; 2280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int dstAlpha = (int) (srcAlpha * alphaMod + 0.5f); 2290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return srcRgb | (dstAlpha << 24); 230bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 231bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 232bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio /** 2330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Listener called when the user selects a day in the day picker view. 2340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final OnDaySelectedListener mOnDaySelectedListener = new OnDaySelectedListener() { 2360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void onDaySelected(DayPickerView view, Calendar day) { 2380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mCurrentDate.setTimeInMillis(day.getTimeInMillis()); 2390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onDateChanged(true, true); 2400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }; 2420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 2440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Listener called when the user selects a year in the year picker view. 2450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final OnYearSelectedListener mOnYearSelectedListener = new OnYearSelectedListener() { 2470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void onYearChanged(YearPickerView view, int year) { 2490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // If the newly selected month / year does not contain the 2500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // currently selected day number, change the selected day number 2510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // to the last day of the selected month or year. 2520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30 2530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013 2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH); 2550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int month = mCurrentDate.get(Calendar.MONTH); 2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int daysInMonth = getDaysInMonth(month, year); 2570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (day > daysInMonth) { 2580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth); 2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mCurrentDate.set(Calendar.YEAR, year); 2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onDateChanged(true, true); 2630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Automatically switch to day picker. 2650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentView(VIEW_MONTH_DAY); 266e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount 267e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount // Switch focus back to the year text. 268e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mHeaderYear.requestFocus(); 2690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }; 2710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 2730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Listener called when the user clicks on a header item. 2740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 275ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette private final OnClickListener mOnHeaderClickListener = v -> { 276ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette tryVibrate(); 277ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette 278ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette switch (v.getId()) { 279ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette case R.id.date_picker_header_year: 280ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette setCurrentView(VIEW_YEAR); 281ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette break; 282ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette case R.id.date_picker_header_date: 283ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette setCurrentView(VIEW_MONTH_DAY); 284ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette break; 2850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }; 2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette protected void onLocaleChanged(Locale locale) { 2900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TextView headerYear = mHeaderYear; 2910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (headerYear == null) { 2920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Abort, we haven't initialized yet. This method will get called 2930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // again later after everything has been set up. 2940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return; 295bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 296bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 2970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Update the date formatter. 298ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette mMonthDayFormat = DateFormat.getInstanceForSkeleton("EMMMd", locale); 299c3e5a82691ac9094189a000430eab939e9020b2bAlan Viverette mMonthDayFormat.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE); 300ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette mYearFormat = DateFormat.getInstanceForSkeleton("y", locale); 301bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Update the header text. 3030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onCurrentDateChanged(false); 3040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 305bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private void onCurrentDateChanged(boolean announce) { 3070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (mHeaderYear == null) { 3080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Abort, we haven't initialized yet. This method will get called 3090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // again later after everything has been set up. 3100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return; 311bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 312bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String year = mYearFormat.format(mCurrentDate.getTime()); 3140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setText(year); 315bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String monthDay = mMonthDayFormat.format(mCurrentDate.getTime()); 3170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setText(monthDay); 318bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // TODO: This should use live regions. 320bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (announce) { 321dd80f0065c0088bff30f9ce5e166df47ddf10690Andrei Stingaceanu mAnimator.announceForAccessibility(getFormattedCurrentDate()); 322bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 323bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 324bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 325bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private void setCurrentView(final int viewIndex) { 326bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio switch (viewIndex) { 3270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette case VIEW_MONTH_DAY: 3280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mDayPickerView.setDate(mCurrentDate.getTimeInMillis()); 3290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 330bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentView != viewIndex) { 3310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setActivated(true); 3320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setActivated(false); 3330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAnimator.setDisplayedChild(VIEW_MONTH_DAY); 334bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentView = viewIndex; 335bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 336bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 337bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mAnimator.announceForAccessibility(mSelectDay); 338bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio break; 3390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette case VIEW_YEAR: 340e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount final int year = mCurrentDate.get(Calendar.YEAR); 341e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mYearPickerView.setYear(year); 342ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette mYearPickerView.post(() -> { 343ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette mYearPickerView.requestFocus(); 344ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette final View selected = mYearPickerView.getSelectedView(); 345ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette if (selected != null) { 346ca38c43604162e0dd532bec675e67f18fd400ae8Alan Viverette selected.requestFocus(); 347e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount } 348e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount }); 3490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 350bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentView != viewIndex) { 3510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setActivated(false); 3520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setActivated(true); 3530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAnimator.setDisplayedChild(VIEW_YEAR); 354bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentView = viewIndex; 355bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 356bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 357bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mAnimator.announceForAccessibility(mSelectYear); 358bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio break; 359bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 360bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 361bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 362bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 363f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme public void init(int year, int month, int dayOfMonth, 364bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio DatePicker.OnDateChangedListener callBack) { 365f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme setDate(year, month, dayOfMonth); 3660cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, false); 367a9a75f506efe7e63078bed661f49992e501846f0Alan Viverette 36868640b68099765461d5427fddbb925beaa9d2a6aClara Bayarri mOnDateChangedListener = callBack; 369bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 370bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 371bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 372bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void updateDate(int year, int month, int dayOfMonth) { 373f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme setDate(year, month, dayOfMonth); 374f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme onDateChanged(false, true); 375f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme } 376f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme 377f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme private void setDate(int year, int month, int dayOfMonth) { 378bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.YEAR, year); 379bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.MONTH, month); 380bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); 381f480e8cad5e6cf4fed85a944adc01d96f51e966bFelipe Leme resetAutofilledValue(); 382e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette } 383e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 3840cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette private void onDateChanged(boolean fromUser, boolean callbackToClient) { 3850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int year = mCurrentDate.get(Calendar.YEAR); 3860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 387305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme if (callbackToClient 388305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme && (mOnDateChangedListener != null || mAutoFillChangeListener != null)) { 389e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette final int monthOfYear = mCurrentDate.get(Calendar.MONTH); 390e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH); 391305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme if (mOnDateChangedListener != null) { 392305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme mOnDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth); 393305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme } 394305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme if (mAutoFillChangeListener != null) { 395305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme mAutoFillChangeListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth); 396305b72c92568a2dd2ece08caebd610ec8bd473f4Felipe Leme } 397e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette } 398e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 3990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mDayPickerView.setDate(mCurrentDate.getTimeInMillis()); 4000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mYearPickerView.setYear(year); 401e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 4020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onCurrentDateChanged(fromUser); 403e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 404e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette if (fromUser) { 405e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette tryVibrate(); 4069468c6a28e696f4ddca2c5b9ba312ffb590c3161Alan Viverette } 407bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 408bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 409bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 410bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getYear() { 411bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.get(Calendar.YEAR); 412bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 413bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 414bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 415bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getMonth() { 416bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.get(Calendar.MONTH); 417bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 418bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 419bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 420bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getDayOfMonth() { 421bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.get(Calendar.DAY_OF_MONTH); 422bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 423bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 424bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 425bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setMinDate(long minDate) { 426bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mTempDate.setTimeInMillis(minDate); 427bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR) 4283fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) { 4293fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette // Same day, no-op. 430bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return; 431bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 432bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentDate.before(mTempDate)) { 433bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.setTimeInMillis(minDate); 4340cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, true); 435bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 436bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mMinDate.setTimeInMillis(minDate); 4374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMinDate(minDate); 43850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette mYearPickerView.setRange(mMinDate, mMaxDate); 439bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 440bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 441bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 442bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public Calendar getMinDate() { 443bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mMinDate; 444bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 445bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 446bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 447bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setMaxDate(long maxDate) { 448bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mTempDate.setTimeInMillis(maxDate); 449bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR) 4503fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) { 4513fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette // Same day, no-op. 452bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return; 453bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 454bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentDate.after(mTempDate)) { 455bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.setTimeInMillis(maxDate); 4560cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, true); 457bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 458bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mMaxDate.setTimeInMillis(maxDate); 4594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMaxDate(maxDate); 46050eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette mYearPickerView.setRange(mMinDate, mMaxDate); 461bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 462bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 463bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 464bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public Calendar getMaxDate() { 465bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mMaxDate; 466bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 467bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 468bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 4690a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette public void setFirstDayOfWeek(int firstDayOfWeek) { 4700a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette mFirstDayOfWeek = firstDayOfWeek; 471e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 472e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mDayPickerView.setFirstDayOfWeek(firstDayOfWeek); 4730a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette } 4740a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette 4750a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette @Override 476bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getFirstDayOfWeek() { 4770a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette if (mFirstDayOfWeek != USE_LOCALE) { 4780a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette return mFirstDayOfWeek; 4790a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette } 480bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.getFirstDayOfWeek(); 481bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 482bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 483bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 484bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setEnabled(boolean enabled) { 485f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mContainer.setEnabled(enabled); 486f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mDayPickerView.setEnabled(enabled); 487f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mYearPickerView.setEnabled(enabled); 488f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mHeaderYear.setEnabled(enabled); 489f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mHeaderMonthDay.setEnabled(enabled); 490bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 491bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 492bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 493bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean isEnabled() { 4940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return mContainer.isEnabled(); 495bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 496bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 497bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 498bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public CalendarView getCalendarView() { 499f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette throw new UnsupportedOperationException("Not supported by calendar-mode DatePicker"); 500bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 501bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 502bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 503bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setCalendarViewShown(boolean shown) { 504bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio // No-op for compatibility with the old DatePicker. 505bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 506bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 507bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 508bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean getCalendarViewShown() { 509bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return false; 510bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 511bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 512bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 513bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setSpinnersShown(boolean shown) { 514bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio // No-op for compatibility with the old DatePicker. 515bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 516bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 517bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 518bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean getSpinnersShown() { 519bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return false; 520bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 521bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 522bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 523bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void onConfigurationChanged(Configuration newConfig) { 5240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentLocale(newConfig.locale); 525bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 526bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 527bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 528bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public Parcelable onSaveInstanceState(Parcelable superState) { 529bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int year = mCurrentDate.get(Calendar.YEAR); 530bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int month = mCurrentDate.get(Calendar.MONTH); 531bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH); 532bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 533bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio int listPosition = -1; 534bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio int listPositionOffset = -1; 535bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 5360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (mCurrentView == VIEW_MONTH_DAY) { 537bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio listPosition = mDayPickerView.getMostVisiblePosition(); 5380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } else if (mCurrentView == VIEW_YEAR) { 539bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio listPosition = mYearPickerView.getFirstVisiblePosition(); 540bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio listPositionOffset = mYearPickerView.getFirstPositionOffset(); 541bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 542bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 543bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return new SavedState(superState, year, month, day, mMinDate.getTimeInMillis(), 544bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mMaxDate.getTimeInMillis(), mCurrentView, listPosition, listPositionOffset); 545bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 546bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 547bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 548bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void onRestoreInstanceState(Parcelable state) { 5496b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (state instanceof SavedState) { 5506b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final SavedState ss = (SavedState) state; 5516b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5526b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette // TODO: Move instance state into DayPickerView, YearPickerView. 5536b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay()); 5546b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mMinDate.setTimeInMillis(ss.getMinDate()); 5556b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mMaxDate.setTimeInMillis(ss.getMaxDate()); 5566b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5576b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette onCurrentDateChanged(false); 5586b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5596b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final int currentView = ss.getCurrentView(); 5606b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette setCurrentView(currentView); 5616b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5626b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final int listPosition = ss.getListPosition(); 5636b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (listPosition != -1) { 5646b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (currentView == VIEW_MONTH_DAY) { 5656b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mDayPickerView.setPosition(listPosition); 5666b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette } else if (currentView == VIEW_YEAR) { 5676b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final int listPositionOffset = ss.getListPositionOffset(); 5686b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset); 5696b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette } 570bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 571bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 572bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 573bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 574bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 575bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 576bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio onPopulateAccessibilityEvent(event); 577bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return true; 578bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 579bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 580a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 581a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return DatePicker.class.getName(); 582bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 583bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 584bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public static int getDaysInMonth(int month, int year) { 585bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio switch (month) { 586bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.JANUARY: 587bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.MARCH: 588bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.MAY: 589bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.JULY: 590bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.AUGUST: 591bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.OCTOBER: 592bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.DECEMBER: 593bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return 31; 594bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.APRIL: 595bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.JUNE: 596bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.SEPTEMBER: 597bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.NOVEMBER: 598bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return 30; 599bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.FEBRUARY: 600bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return (year % 4 == 0) ? 29 : 28; 601bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio default: 602bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio throw new IllegalArgumentException("Invalid Month"); 603bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 604bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 605bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 6060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private void tryVibrate() { 607bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE); 608bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 609bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio} 610