DatePickerCalendarDelegate.java revision a9a75f506efe7e63078bed661f49992e501846f0
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 196b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viveretteimport com.android.internal.R; 206b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.annotation.Nullable; 22bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.Context; 23bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.ColorStateList; 24bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.Configuration; 25bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.Resources; 26bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.TypedArray; 27bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.os.Parcelable; 28bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.text.format.DateFormat; 29bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.text.format.DateUtils; 30bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.util.AttributeSet; 310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.StateSet; 32bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.HapticFeedbackConstants; 33bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.LayoutInflater; 34bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.View; 350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.View.OnClickListener; 360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.ViewGroup; 37bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.accessibility.AccessibilityEvent; 380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.DayPickerView.OnDaySelectedListener; 390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.YearPickerView.OnYearSelectedListener; 40bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 41bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.text.SimpleDateFormat; 42bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Calendar; 43bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Locale; 44bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 45bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/** 46bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * A delegate for picking up a date (day / month / year). 47bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteclass DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { 490a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette private static final int USE_LOCALE = 0; 50bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 51bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int UNINITIALIZED = -1; 520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private static final int VIEW_MONTH_DAY = 0; 530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private static final int VIEW_YEAR = 1; 54bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 55bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int DEFAULT_START_YEAR = 1900; 56bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int DEFAULT_END_YEAR = 2100; 57bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 58bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private static final int ANIMATION_DURATION = 300; 59bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 6060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette private static final int[] ATTRS_TEXT_COLOR = new int[] { 6160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette com.android.internal.R.attr.textColor}; 6260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette private static final int[] ATTRS_DISABLED_ALPHA = new int[] { 630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette com.android.internal.R.attr.disabledAlpha}; 64bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private SimpleDateFormat mYearFormat; 660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private SimpleDateFormat mMonthDayFormat; 677119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Top-level container. 690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private ViewGroup mContainer; 707119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Header views. 720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private TextView mHeaderYear; 730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private TextView mHeaderMonthDay; 747119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Picker views. 760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private ViewAnimator mAnimator; 77bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private DayPickerView mDayPickerView; 78bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private YearPickerView mYearPickerView; 79bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 80bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio // Accessibility strings. 81bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private String mSelectDay; 82bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private String mSelectYear; 83bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 84bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private DatePicker.OnDateChangedListener mDateChangedListener; 85bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 86bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private int mCurrentView = UNINITIALIZED; 87bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 88452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mCurrentDate; 89452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mTempDate; 90452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mMinDate; 91452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette private final Calendar mMaxDate; 92bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 930a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette private int mFirstDayOfWeek = USE_LOCALE; 940a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette 953053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs, 96bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio int defStyleAttr, int defStyleRes) { 97bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio super(delegator, context); 98bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final Locale locale = mCurrentLocale; 100452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mCurrentDate = Calendar.getInstance(locale); 101452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mTempDate = Calendar.getInstance(locale); 102452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mMinDate = Calendar.getInstance(locale); 103452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette mMaxDate = Calendar.getInstance(locale); 104bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 10549e6c4adbfad8cac28a0c7c68918b443a64a07d8You Kim mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1); 10649e6c4adbfad8cac28a0c7c68918b443a64a07d8You Kim mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31); 107bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 10860727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette final Resources res = mDelegator.getResources(); 109bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final TypedArray a = mContext.obtainStyledAttributes(attrs, 110bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio R.styleable.DatePicker, defStyleAttr, defStyleRes); 111bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( 112bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio Context.LAYOUT_INFLATER_SERVICE); 113bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int layoutResourceId = a.getResourceId( 1140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.DatePicker_internalLayout, R.layout.date_picker_material); 1150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up and attach container. 117f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator, false); 118f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mDelegator.addView(mContainer); 119bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up header views. 1210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header); 1220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year); 1230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setOnClickListener(mOnHeaderClickListener); 1240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date); 1250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener); 126ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette 1270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // For the sake of backwards compatibility, attempt to extract the text 1280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // color from the header month text appearance. If it's set, we'll let 1290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // that override the "real" header text color. 1300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette ColorStateList headerTextColor = null; 131bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @SuppressWarnings("deprecation") 1330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int monthHeaderTextAppearance = a.getResourceId( 1344e5168fae43e783a35c5bc731e500196005268fbAlan Viverette R.styleable.DatePicker_headerMonthTextAppearance, 0); 1350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (monthHeaderTextAppearance != 0) { 1360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TypedArray textAppearance = mContext.obtainStyledAttributes(null, 1370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette ATTRS_TEXT_COLOR, 0, monthHeaderTextAppearance); 1380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final ColorStateList legacyHeaderTextColor = textAppearance.getColorStateList(0); 1390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette headerTextColor = applyLegacyColorFixes(legacyHeaderTextColor); 1400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette textAppearance.recycle(); 141bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 14260727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette 1430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (headerTextColor == null) { 1440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette headerTextColor = a.getColorStateList(R.styleable.DatePicker_headerTextColor); 14560727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette } 14660727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette 1470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (headerTextColor != null) { 1480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setTextColor(headerTextColor); 1490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setTextColor(headerTextColor); 15060727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette } 151bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up header background, if available. 1530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (a.hasValueOrEmpty(R.styleable.DatePicker_headerBackground)) { 1540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette header.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground)); 1550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 15760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette a.recycle(); 15860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette 1590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up picker container. 1600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator); 1610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up day picker view. 1630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker); 164e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek); 1654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMinDate(mMinDate.getTimeInMillis()); 1664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis()); 1674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setDate(mCurrentDate.getTimeInMillis()); 168e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener); 16950eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 1700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up year picker view. 1710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker); 1722a90fa6d94b7d31e997493d2d0601e5129ec7c3eAlan Viverette mYearPickerView.setRange(mMinDate, mMaxDate); 173e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR)); 1740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener); 1754e5168fae43e783a35c5bc731e500196005268fbAlan Viverette 1760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up content descriptions. 177bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mSelectDay = res.getString(R.string.select_day); 178bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mSelectYear = res.getString(R.string.select_year); 179bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 1800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Initialize for current locale. This also initializes the date, so no 1810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // need to call onDateChanged. 1820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onLocaleChanged(mCurrentLocale); 1830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentView(VIEW_MONTH_DAY); 1850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 1880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * The legacy text color might have been poorly defined. Ensures that it 1890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * has an appropriate activated state, using the selected state if one 1900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * exists or modifying the default text color otherwise. 1910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * 1920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param color a legacy text color, or {@code null} 1930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @return a color state list with an appropriate activated state, or 1940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * {@code null} if a valid activated state could not be generated 1950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 1960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Nullable 1970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private ColorStateList applyLegacyColorFixes(@Nullable ColorStateList color) { 1980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (color == null || color.hasState(R.attr.state_activated)) { 1990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return color; 2000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int activatedColor; 2030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int defaultColor; 2040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (color.hasState(R.attr.state_selected)) { 2050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette activatedColor = color.getColorForState(StateSet.get( 2060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_SELECTED), 0); 2070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette defaultColor = color.getColorForState(StateSet.get( 2080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette StateSet.VIEW_STATE_ENABLED), 0); 2090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } else { 2100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette activatedColor = color.getDefaultColor(); 2110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Generate a non-activated color using the disabled alpha. 2130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TypedArray ta = mContext.obtainStyledAttributes(ATTRS_DISABLED_ALPHA); 2140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final float disabledAlpha = ta.getFloat(0, 0.30f); 2150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette defaultColor = multiplyAlphaComponent(activatedColor, disabledAlpha); 2160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2177119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 2180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (activatedColor == 0 || defaultColor == 0) { 2190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // We somehow failed to obtain the colors. 2200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return null; 2210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2227119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette 2230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int[][] stateSet = new int[][] {{ R.attr.state_activated }, {}}; 2240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int[] colors = new int[] { activatedColor, defaultColor }; 2250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return new ColorStateList(stateSet, colors); 2260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 227bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 2280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private int multiplyAlphaComponent(int color, float alphaMod) { 2290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int srcRgb = color & 0xFFFFFF; 2300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int srcAlpha = (color >> 24) & 0xFF; 2310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int dstAlpha = (int) (srcAlpha * alphaMod + 0.5f); 2320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return srcRgb | (dstAlpha << 24); 233bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 234bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 235bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio /** 2360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Listener called when the user selects a day in the day picker view. 2370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final OnDaySelectedListener mOnDaySelectedListener = new OnDaySelectedListener() { 2390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void onDaySelected(DayPickerView view, Calendar day) { 2410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mCurrentDate.setTimeInMillis(day.getTimeInMillis()); 2420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onDateChanged(true, true); 2430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }; 2450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 2470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Listener called when the user selects a year in the year picker view. 2480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final OnYearSelectedListener mOnYearSelectedListener = new OnYearSelectedListener() { 2500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void onYearChanged(YearPickerView view, int year) { 2520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // If the newly selected month / year does not contain the 2530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // currently selected day number, change the selected day number 2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // to the last day of the selected month or year. 2550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30 2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013 2570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH); 2580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int month = mCurrentDate.get(Calendar.MONTH); 2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int daysInMonth = getDaysInMonth(month, year); 2600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (day > daysInMonth) { 2610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth); 2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mCurrentDate.set(Calendar.YEAR, year); 2650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onDateChanged(true, true); 2660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Automatically switch to day picker. 2680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentView(VIEW_MONTH_DAY); 269e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount 270e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount // Switch focus back to the year text. 271e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mHeaderYear.requestFocus(); 2720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }; 2740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 2760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Listener called when the user clicks on a header item. 2770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final OnClickListener mOnHeaderClickListener = new OnClickListener() { 2790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void onClick(View v) { 2810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette tryVibrate(); 2820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette switch (v.getId()) { 2840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette case R.id.date_picker_header_year: 2850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentView(VIEW_YEAR); 2860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette break; 2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette case R.id.date_picker_header_date: 2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentView(VIEW_MONTH_DAY); 2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette break; 2900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }; 2930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 2950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette protected void onLocaleChanged(Locale locale) { 2960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TextView headerYear = mHeaderYear; 2970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (headerYear == null) { 2980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Abort, we haven't initialized yet. This method will get called 2990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // again later after everything has been set up. 3000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return; 301bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 302bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Update the date formatter. 3040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String datePattern = DateFormat.getBestDateTimePattern(locale, "EMMMd"); 3050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mMonthDayFormat = new SimpleDateFormat(datePattern, locale); 3060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mYearFormat = new SimpleDateFormat("y", locale); 307bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Update the header text. 3090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onCurrentDateChanged(false); 3100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 311bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private void onCurrentDateChanged(boolean announce) { 3130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (mHeaderYear == null) { 3140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Abort, we haven't initialized yet. This method will get called 3150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // again later after everything has been set up. 3160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return; 317bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 318bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String year = mYearFormat.format(mCurrentDate.getTime()); 3200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setText(year); 321bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String monthDay = mMonthDayFormat.format(mCurrentDate.getTime()); 3230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setText(monthDay); 324bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // TODO: This should use live regions. 326bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (announce) { 3270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final long millis = mCurrentDate.getTimeInMillis(); 3280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR; 3290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String fullDateText = DateUtils.formatDateTime(mContext, millis, flags); 330bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mAnimator.announceForAccessibility(fullDateText); 331bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 332bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 333bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 334bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio private void setCurrentView(final int viewIndex) { 335bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio switch (viewIndex) { 3360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette case VIEW_MONTH_DAY: 3370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mDayPickerView.setDate(mCurrentDate.getTimeInMillis()); 3380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 339bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentView != viewIndex) { 3400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setActivated(true); 3410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setActivated(false); 3420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAnimator.setDisplayedChild(VIEW_MONTH_DAY); 343bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentView = viewIndex; 344bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 345bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 346bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mAnimator.announceForAccessibility(mSelectDay); 347bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio break; 3480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette case VIEW_YEAR: 349e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount final int year = mCurrentDate.get(Calendar.YEAR); 350e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mYearPickerView.setYear(year); 351e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mYearPickerView.post(new Runnable() { 352e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount @Override 353e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount public void run() { 354e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount mYearPickerView.requestFocus(); 355e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount final View selected = mYearPickerView.getSelectedView(); 356e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount if (selected != null) { 357e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount selected.requestFocus(); 358e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount } 359e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount } 360e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount }); 3610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 362bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentView != viewIndex) { 3630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderMonthDay.setActivated(false); 3640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mHeaderYear.setActivated(true); 3650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAnimator.setDisplayedChild(VIEW_YEAR); 366bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentView = viewIndex; 367bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 368bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 369bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mAnimator.announceForAccessibility(mSelectYear); 370bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio break; 371bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 372bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 373bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 374bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 375bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void init(int year, int monthOfYear, int dayOfMonth, 376bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio DatePicker.OnDateChangedListener callBack) { 377bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.YEAR, year); 378bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.MONTH, monthOfYear); 379bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); 380e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 3810cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, false); 382a9a75f506efe7e63078bed661f49992e501846f0Alan Viverette 383a9a75f506efe7e63078bed661f49992e501846f0Alan Viverette mDateChangedListener = callBack; 384bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 385bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 386bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 387bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void updateDate(int year, int month, int dayOfMonth) { 388bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.YEAR, year); 389bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.MONTH, month); 390bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); 391e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 3920cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, true); 393e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette } 394e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 3950cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette private void onDateChanged(boolean fromUser, boolean callbackToClient) { 3960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int year = mCurrentDate.get(Calendar.YEAR); 3970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 3980cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette if (callbackToClient && mDateChangedListener != null) { 399e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette final int monthOfYear = mCurrentDate.get(Calendar.MONTH); 400e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH); 401e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette mDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth); 402e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette } 403e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 4040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mDayPickerView.setDate(mCurrentDate.getTimeInMillis()); 4050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mYearPickerView.setYear(year); 406e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 4070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette onCurrentDateChanged(fromUser); 408e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette 409e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette if (fromUser) { 410e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette tryVibrate(); 4119468c6a28e696f4ddca2c5b9ba312ffb590c3161Alan Viverette } 412bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 413bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 414bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 415bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getYear() { 416bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.get(Calendar.YEAR); 417bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 418bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 419bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 420bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getMonth() { 421bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.get(Calendar.MONTH); 422bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 423bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 424bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 425bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getDayOfMonth() { 426bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.get(Calendar.DAY_OF_MONTH); 427bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 428bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 429bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 430bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setMinDate(long minDate) { 431bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mTempDate.setTimeInMillis(minDate); 432bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR) 433bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) { 434bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return; 435bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 436bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentDate.before(mTempDate)) { 437bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.setTimeInMillis(minDate); 4380cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, true); 439bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 440bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mMinDate.setTimeInMillis(minDate); 4414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMinDate(minDate); 44250eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette mYearPickerView.setRange(mMinDate, mMaxDate); 443bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 444bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 445bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 446bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public Calendar getMinDate() { 447bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mMinDate; 448bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 449bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 450bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 451bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setMaxDate(long maxDate) { 452bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mTempDate.setTimeInMillis(maxDate); 453bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR) 454bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) { 455bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return; 456bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 457bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio if (mCurrentDate.after(mTempDate)) { 458bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mCurrentDate.setTimeInMillis(maxDate); 4590cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette onDateChanged(false, true); 460bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 461bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mMaxDate.setTimeInMillis(maxDate); 4624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayPickerView.setMaxDate(maxDate); 46350eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette mYearPickerView.setRange(mMinDate, mMaxDate); 464bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 465bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 466bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 467bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public Calendar getMaxDate() { 468bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mMaxDate; 469bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 470bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 471bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 4720a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette public void setFirstDayOfWeek(int firstDayOfWeek) { 4730a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette mFirstDayOfWeek = firstDayOfWeek; 474e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 475e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mDayPickerView.setFirstDayOfWeek(firstDayOfWeek); 4760a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette } 4770a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette 4780a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette @Override 479bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getFirstDayOfWeek() { 4800a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette if (mFirstDayOfWeek != USE_LOCALE) { 4810a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette return mFirstDayOfWeek; 4820a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette } 483bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return mCurrentDate.getFirstDayOfWeek(); 484bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 485bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 486bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 487bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setEnabled(boolean enabled) { 488f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mContainer.setEnabled(enabled); 489f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mDayPickerView.setEnabled(enabled); 490f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mYearPickerView.setEnabled(enabled); 491f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mHeaderYear.setEnabled(enabled); 492f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette mHeaderMonthDay.setEnabled(enabled); 493bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 494bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 495bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 496bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean isEnabled() { 4970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return mContainer.isEnabled(); 498bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 499bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 500bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 501bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public CalendarView getCalendarView() { 502f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette throw new UnsupportedOperationException("Not supported by calendar-mode DatePicker"); 503bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 504bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 505bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 506bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setCalendarViewShown(boolean shown) { 507bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio // No-op for compatibility with the old DatePicker. 508bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 509bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 510bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 511bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean getCalendarViewShown() { 512bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return false; 513bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 514bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 515bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 516bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void setSpinnersShown(boolean shown) { 517bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio // No-op for compatibility with the old DatePicker. 518bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 519bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 520bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 521bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean getSpinnersShown() { 522bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return false; 523bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 524bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 525bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 526bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void onConfigurationChanged(Configuration newConfig) { 5270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentLocale(newConfig.locale); 528bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 529bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 530bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 531bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public Parcelable onSaveInstanceState(Parcelable superState) { 532bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int year = mCurrentDate.get(Calendar.YEAR); 533bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int month = mCurrentDate.get(Calendar.MONTH); 534bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH); 535bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 536bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio int listPosition = -1; 537bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio int listPositionOffset = -1; 538bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 5390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (mCurrentView == VIEW_MONTH_DAY) { 540bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio listPosition = mDayPickerView.getMostVisiblePosition(); 5410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } else if (mCurrentView == VIEW_YEAR) { 542bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio listPosition = mYearPickerView.getFirstVisiblePosition(); 543bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio listPositionOffset = mYearPickerView.getFirstPositionOffset(); 544bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 545bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 546bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return new SavedState(superState, year, month, day, mMinDate.getTimeInMillis(), 547bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mMaxDate.getTimeInMillis(), mCurrentView, listPosition, listPositionOffset); 548bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 549bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 550bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 551bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void onRestoreInstanceState(Parcelable state) { 5526b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (state instanceof SavedState) { 5536b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final SavedState ss = (SavedState) state; 5546b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5556b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette // TODO: Move instance state into DayPickerView, YearPickerView. 5566b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay()); 5576b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mMinDate.setTimeInMillis(ss.getMinDate()); 5586b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mMaxDate.setTimeInMillis(ss.getMaxDate()); 5596b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5606b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette onCurrentDateChanged(false); 5616b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5626b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final int currentView = ss.getCurrentView(); 5636b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette setCurrentView(currentView); 5646b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette 5656b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final int listPosition = ss.getListPosition(); 5666b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (listPosition != -1) { 5676b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette if (currentView == VIEW_MONTH_DAY) { 5686b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mDayPickerView.setPosition(listPosition); 5696b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette } else if (currentView == VIEW_YEAR) { 5706b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette final int listPositionOffset = ss.getListPositionOffset(); 5716b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset); 5726b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette } 573bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 574bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 575bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 576bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 577bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 578bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 579bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio onPopulateAccessibilityEvent(event); 580bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return true; 581bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 582bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 583bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio @Override 584bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 585bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio event.getText().add(mCurrentDate.getTime().toString()); 586bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 587bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 588a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 589a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return DatePicker.class.getName(); 590bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 591bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 592bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public static int getDaysInMonth(int month, int year) { 593bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio switch (month) { 594bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.JANUARY: 595bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.MARCH: 596bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.MAY: 597bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.JULY: 598bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.AUGUST: 599bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.OCTOBER: 600bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.DECEMBER: 601bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return 31; 602bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.APRIL: 603bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.JUNE: 604bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.SEPTEMBER: 605bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.NOVEMBER: 606bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return 30; 607bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio case Calendar.FEBRUARY: 608bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio return (year % 4 == 0) ? 29 : 28; 609bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio default: 610bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio throw new IllegalArgumentException("Invalid Month"); 611bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 612bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 613bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 6140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private void tryVibrate() { 615bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE); 616bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 617bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio} 618