13e9818e0267619fecebd55095ab26c53eff92e93James Kung/* 23e9818e0267619fecebd55095ab26c53eff92e93James Kung * Copyright (C) 2013 The Android Open Source Project 33e9818e0267619fecebd55095ab26c53eff92e93James Kung * 43e9818e0267619fecebd55095ab26c53eff92e93James Kung * Licensed under the Apache License, Version 2.0 (the "License"); 53e9818e0267619fecebd55095ab26c53eff92e93James Kung * you may not use this file except in compliance with the License. 63e9818e0267619fecebd55095ab26c53eff92e93James Kung * You may obtain a copy of the License at 73e9818e0267619fecebd55095ab26c53eff92e93James Kung * 83e9818e0267619fecebd55095ab26c53eff92e93James Kung * http://www.apache.org/licenses/LICENSE-2.0 93e9818e0267619fecebd55095ab26c53eff92e93James Kung * 103e9818e0267619fecebd55095ab26c53eff92e93James Kung * Unless required by applicable law or agreed to in writing, software 113e9818e0267619fecebd55095ab26c53eff92e93James Kung * distributed under the License is distributed on an "AS IS" BASIS, 123e9818e0267619fecebd55095ab26c53eff92e93James Kung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e9818e0267619fecebd55095ab26c53eff92e93James Kung * See the License for the specific language governing permissions and 143e9818e0267619fecebd55095ab26c53eff92e93James Kung * limitations under the License. 153e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 163e9818e0267619fecebd55095ab26c53eff92e93James Kung 173e9818e0267619fecebd55095ab26c53eff92e93James Kungpackage com.android.datetimepicker.date; 183e9818e0267619fecebd55095ab26c53eff92e93James Kung 192e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport android.animation.ObjectAnimator; 203e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.app.Activity; 213e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.app.DialogFragment; 22cb3f2522609186db6239ad154af275957118295cSam Blitzsteinimport android.content.res.Resources; 233e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.os.Bundle; 24cb3f2522609186db6239ad154af275957118295cSam Blitzsteinimport android.text.format.DateUtils; 253e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.util.Log; 263e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.LayoutInflater; 273e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.View; 283e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.View.OnClickListener; 293e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.ViewGroup; 303e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.view.Window; 31f4d8e7a2271df7025f61d5ed086455a00b3fd325James Kungimport android.view.WindowManager; 32f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kungimport android.view.animation.AlphaAnimation; 33f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kungimport android.view.animation.Animation; 343e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.widget.Button; 35f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kungimport android.widget.LinearLayout; 363e9818e0267619fecebd55095ab26c53eff92e93James Kungimport android.widget.TextView; 373e9818e0267619fecebd55095ab26c53eff92e93James Kung 383fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowskiimport com.android.datetimepicker.HapticFeedbackController; 393e9818e0267619fecebd55095ab26c53eff92e93James Kungimport com.android.datetimepicker.R; 403e9818e0267619fecebd55095ab26c53eff92e93James Kungimport com.android.datetimepicker.Utils; 413e9818e0267619fecebd55095ab26c53eff92e93James Kungimport com.android.datetimepicker.date.SimpleMonthAdapter.CalendarDay; 423e9818e0267619fecebd55095ab26c53eff92e93James Kung 433e9818e0267619fecebd55095ab26c53eff92e93James Kungimport java.text.SimpleDateFormat; 443e9818e0267619fecebd55095ab26c53eff92e93James Kungimport java.util.Calendar; 452e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport java.util.HashSet; 462e00aa34c051111529290cf23c6ba940c2c0c142James Kungimport java.util.Iterator; 473e9818e0267619fecebd55095ab26c53eff92e93James Kungimport java.util.Locale; 483e9818e0267619fecebd55095ab26c53eff92e93James Kung 493e9818e0267619fecebd55095ab26c53eff92e93James Kung/** 503e9818e0267619fecebd55095ab26c53eff92e93James Kung * Dialog allowing users to select a date. 513e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 523e9818e0267619fecebd55095ab26c53eff92e93James Kungpublic class DatePickerDialog extends DialogFragment implements 53f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung OnClickListener, DatePickerController { 543e9818e0267619fecebd55095ab26c53eff92e93James Kung 553e9818e0267619fecebd55095ab26c53eff92e93James Kung private static final String TAG = "DatePickerDialog"; 563e9818e0267619fecebd55095ab26c53eff92e93James Kung 572e00aa34c051111529290cf23c6ba940c2c0c142James Kung private static final int UNINITIALIZED = -1; 58f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final int MONTH_AND_DAY_VIEW = 0; 59f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final int YEAR_VIEW = 1; 603e9818e0267619fecebd55095ab26c53eff92e93James Kung 61f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_SELECTED_YEAR = "year"; 62f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_SELECTED_MONTH = "month"; 63f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_SELECTED_DAY = "day"; 642e00aa34c051111529290cf23c6ba940c2c0c142James Kung private static final String KEY_LIST_POSITION = "list_position"; 65f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_WEEK_START = "week_start"; 66f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_YEAR_START = "year_start"; 67f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_YEAR_END = "year_end"; 68f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private static final String KEY_CURRENT_VIEW = "current_view"; 6971492ab60892087f3e989b876b82f5c0249b3b14James Kung private static final String KEY_LIST_POSITION_OFFSET = "list_position_offset"; 703e9818e0267619fecebd55095ab26c53eff92e93James Kung 713e9818e0267619fecebd55095ab26c53eff92e93James Kung private static final int DEFAULT_START_YEAR = 1900; 723e9818e0267619fecebd55095ab26c53eff92e93James Kung private static final int DEFAULT_END_YEAR = 2100; 733e9818e0267619fecebd55095ab26c53eff92e93James Kung 742e00aa34c051111529290cf23c6ba940c2c0c142James Kung private static final int ANIMATION_DURATION = 300; 752e00aa34c051111529290cf23c6ba940c2c0c142James Kung private static final int ANIMATION_DELAY = 500; 76f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung 773e9818e0267619fecebd55095ab26c53eff92e93James Kung private static SimpleDateFormat YEAR_FORMAT = new SimpleDateFormat("yyyy", Locale.getDefault()); 783e9818e0267619fecebd55095ab26c53eff92e93James Kung private static SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("dd", Locale.getDefault()); 793e9818e0267619fecebd55095ab26c53eff92e93James Kung 803e9818e0267619fecebd55095ab26c53eff92e93James Kung private final Calendar mCalendar = Calendar.getInstance(); 813e9818e0267619fecebd55095ab26c53eff92e93James Kung private OnDateSetListener mCallBack; 822e00aa34c051111529290cf23c6ba940c2c0c142James Kung private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>(); 833e9818e0267619fecebd55095ab26c53eff92e93James Kung 84cb3f2522609186db6239ad154af275957118295cSam Blitzstein private AccessibleDateAnimator mAnimator; 853e9818e0267619fecebd55095ab26c53eff92e93James Kung 863e9818e0267619fecebd55095ab26c53eff92e93James Kung private TextView mDayOfWeekView; 87f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private LinearLayout mMonthAndDayView; 88f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private TextView mSelectedMonthTextView; 89f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private TextView mSelectedDayTextView; 903e9818e0267619fecebd55095ab26c53eff92e93James Kung private TextView mYearView; 913e9818e0267619fecebd55095ab26c53eff92e93James Kung private DayPickerView mDayPickerView; 923e9818e0267619fecebd55095ab26c53eff92e93James Kung private YearPickerView mYearPickerView; 933e9818e0267619fecebd55095ab26c53eff92e93James Kung private Button mDoneButton; 943e9818e0267619fecebd55095ab26c53eff92e93James Kung 952e00aa34c051111529290cf23c6ba940c2c0c142James Kung private int mCurrentView = UNINITIALIZED; 96f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung 973e9818e0267619fecebd55095ab26c53eff92e93James Kung private int mWeekStart = mCalendar.getFirstDayOfWeek(); 983e9818e0267619fecebd55095ab26c53eff92e93James Kung private int mMinYear = DEFAULT_START_YEAR; 993e9818e0267619fecebd55095ab26c53eff92e93James Kung private int mMaxYear = DEFAULT_END_YEAR; 1003e9818e0267619fecebd55095ab26c53eff92e93James Kung 1013fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski private HapticFeedbackController mHapticFeedbackController; 1022e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1032e00aa34c051111529290cf23c6ba940c2c0c142James Kung private boolean mDelayAnimation = true; 1043e9818e0267619fecebd55095ab26c53eff92e93James Kung 105cb3f2522609186db6239ad154af275957118295cSam Blitzstein // Accessibility strings. 106cb3f2522609186db6239ad154af275957118295cSam Blitzstein private String mDayPickerDescription; 107cb3f2522609186db6239ad154af275957118295cSam Blitzstein private String mSelectDay; 108cb3f2522609186db6239ad154af275957118295cSam Blitzstein private String mYearPickerDescription; 109cb3f2522609186db6239ad154af275957118295cSam Blitzstein private String mSelectYear; 110cb3f2522609186db6239ad154af275957118295cSam Blitzstein 1113e9818e0267619fecebd55095ab26c53eff92e93James Kung /** 1123e9818e0267619fecebd55095ab26c53eff92e93James Kung * The callback used to indicate the user is done filling in the date. 1133e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 1143e9818e0267619fecebd55095ab26c53eff92e93James Kung public interface OnDateSetListener { 1153e9818e0267619fecebd55095ab26c53eff92e93James Kung 1163e9818e0267619fecebd55095ab26c53eff92e93James Kung /** 1173e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param view The view associated with this listener. 1183e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param year The year that was set. 1193e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param monthOfYear The month that was set (0-11) for compatibility 1203e9818e0267619fecebd55095ab26c53eff92e93James Kung * with {@link java.util.Calendar}. 1213e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param dayOfMonth The day of the month that was set. 1223e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 1233e9818e0267619fecebd55095ab26c53eff92e93James Kung void onDateSet(DatePickerDialog dialog, int year, int monthOfYear, int dayOfMonth); 1243e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1253e9818e0267619fecebd55095ab26c53eff92e93James Kung 1262e00aa34c051111529290cf23c6ba940c2c0c142James Kung /** 1272e00aa34c051111529290cf23c6ba940c2c0c142James Kung * The callback used to notify other date picker components of a change in selected date. 1282e00aa34c051111529290cf23c6ba940c2c0c142James Kung */ 129385d36f15358e7d035b2e89e395588eb7952ebc2James Kung public interface OnDateChangedListener { 1302e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1312e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onDateChanged(); 1322e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1332e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1342e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1353e9818e0267619fecebd55095ab26c53eff92e93James Kung public DatePickerDialog() { 1363e9818e0267619fecebd55095ab26c53eff92e93James Kung // Empty constructor required for dialog fragment. 1373e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1383e9818e0267619fecebd55095ab26c53eff92e93James Kung 1393e9818e0267619fecebd55095ab26c53eff92e93James Kung /** 1403e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param callBack How the parent is notified that the date is set. 1413e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param year The initial year of the dialog. 1423e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param monthOfYear The initial month of the dialog. 1433e9818e0267619fecebd55095ab26c53eff92e93James Kung * @param dayOfMonth The initial day of the dialog. 1443e9818e0267619fecebd55095ab26c53eff92e93James Kung */ 1453e9818e0267619fecebd55095ab26c53eff92e93James Kung public static DatePickerDialog newInstance(OnDateSetListener callBack, int year, 1463e9818e0267619fecebd55095ab26c53eff92e93James Kung int monthOfYear, 1473e9818e0267619fecebd55095ab26c53eff92e93James Kung int dayOfMonth) { 1483e9818e0267619fecebd55095ab26c53eff92e93James Kung DatePickerDialog ret = new DatePickerDialog(); 1493e9818e0267619fecebd55095ab26c53eff92e93James Kung ret.initialize(callBack, year, monthOfYear, dayOfMonth); 1503e9818e0267619fecebd55095ab26c53eff92e93James Kung return ret; 1513e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1523e9818e0267619fecebd55095ab26c53eff92e93James Kung 1533e9818e0267619fecebd55095ab26c53eff92e93James Kung public void initialize(OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) { 1543e9818e0267619fecebd55095ab26c53eff92e93James Kung mCallBack = callBack; 1553e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.YEAR, year); 1563e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.MONTH, monthOfYear); 1573e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth); 1583e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1593e9818e0267619fecebd55095ab26c53eff92e93James Kung 1603e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 1613e9818e0267619fecebd55095ab26c53eff92e93James Kung public void onCreate(Bundle savedInstanceState) { 1623e9818e0267619fecebd55095ab26c53eff92e93James Kung super.onCreate(savedInstanceState); 1632e00aa34c051111529290cf23c6ba940c2c0c142James Kung final Activity activity = getActivity(); 1642e00aa34c051111529290cf23c6ba940c2c0c142James Kung activity.getWindow().setSoftInputMode( 165f4d8e7a2271df7025f61d5ed086455a00b3fd325James Kung WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 1663e9818e0267619fecebd55095ab26c53eff92e93James Kung if (savedInstanceState != null) { 1673e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.YEAR, savedInstanceState.getInt(KEY_SELECTED_YEAR)); 1683e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.MONTH, savedInstanceState.getInt(KEY_SELECTED_MONTH)); 1693e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.DAY_OF_MONTH, savedInstanceState.getInt(KEY_SELECTED_DAY)); 1703e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1713e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1723e9818e0267619fecebd55095ab26c53eff92e93James Kung 1733e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 1743e9818e0267619fecebd55095ab26c53eff92e93James Kung public void onSaveInstanceState(Bundle outState) { 1753e9818e0267619fecebd55095ab26c53eff92e93James Kung super.onSaveInstanceState(outState); 1763e9818e0267619fecebd55095ab26c53eff92e93James Kung outState.putInt(KEY_SELECTED_YEAR, mCalendar.get(Calendar.YEAR)); 1773e9818e0267619fecebd55095ab26c53eff92e93James Kung outState.putInt(KEY_SELECTED_MONTH, mCalendar.get(Calendar.MONTH)); 1783e9818e0267619fecebd55095ab26c53eff92e93James Kung outState.putInt(KEY_SELECTED_DAY, mCalendar.get(Calendar.DAY_OF_MONTH)); 1793e9818e0267619fecebd55095ab26c53eff92e93James Kung outState.putInt(KEY_WEEK_START, mWeekStart); 1803e9818e0267619fecebd55095ab26c53eff92e93James Kung outState.putInt(KEY_YEAR_START, mMinYear); 1813e9818e0267619fecebd55095ab26c53eff92e93James Kung outState.putInt(KEY_YEAR_END, mMaxYear); 182f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung outState.putInt(KEY_CURRENT_VIEW, mCurrentView); 1832e00aa34c051111529290cf23c6ba940c2c0c142James Kung int listPosition = -1; 1842e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (mCurrentView == MONTH_AND_DAY_VIEW) { 1852e00aa34c051111529290cf23c6ba940c2c0c142James Kung listPosition = mDayPickerView.getMostVisiblePosition(); 1862e00aa34c051111529290cf23c6ba940c2c0c142James Kung } else if (mCurrentView == YEAR_VIEW) { 1872e00aa34c051111529290cf23c6ba940c2c0c142James Kung listPosition = mYearPickerView.getFirstVisiblePosition(); 18871492ab60892087f3e989b876b82f5c0249b3b14James Kung outState.putInt(KEY_LIST_POSITION_OFFSET, mYearPickerView.getFirstPositionOffset()); 1892e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 1902e00aa34c051111529290cf23c6ba940c2c0c142James Kung outState.putInt(KEY_LIST_POSITION, listPosition); 1913e9818e0267619fecebd55095ab26c53eff92e93James Kung } 1923e9818e0267619fecebd55095ab26c53eff92e93James Kung 1933e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 1943e9818e0267619fecebd55095ab26c53eff92e93James Kung public View onCreateView(LayoutInflater inflater, ViewGroup container, 1953e9818e0267619fecebd55095ab26c53eff92e93James Kung Bundle savedInstanceState) { 1963e9818e0267619fecebd55095ab26c53eff92e93James Kung Log.d(TAG, "onCreateView: "); 1973e9818e0267619fecebd55095ab26c53eff92e93James Kung getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); 1983e9818e0267619fecebd55095ab26c53eff92e93James Kung 1993e9818e0267619fecebd55095ab26c53eff92e93James Kung View view = inflater.inflate(R.layout.date_picker_dialog, null); 2003e9818e0267619fecebd55095ab26c53eff92e93James Kung 2013e9818e0267619fecebd55095ab26c53eff92e93James Kung mDayOfWeekView = (TextView) view.findViewById(R.id.date_picker_header); 202f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mMonthAndDayView = (LinearLayout) view.findViewById(R.id.date_picker_month_and_day); 203f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mMonthAndDayView.setOnClickListener(this); 204f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mSelectedMonthTextView = (TextView) view.findViewById(R.id.date_picker_month); 205f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mSelectedDayTextView = (TextView) view.findViewById(R.id.date_picker_day); 2063e9818e0267619fecebd55095ab26c53eff92e93James Kung mYearView = (TextView) view.findViewById(R.id.date_picker_year); 2073e9818e0267619fecebd55095ab26c53eff92e93James Kung mYearView.setOnClickListener(this); 2083e9818e0267619fecebd55095ab26c53eff92e93James Kung 2092e00aa34c051111529290cf23c6ba940c2c0c142James Kung int listPosition = -1; 21071492ab60892087f3e989b876b82f5c0249b3b14James Kung int listPositionOffset = 0; 211f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung int currentView = MONTH_AND_DAY_VIEW; 2123e9818e0267619fecebd55095ab26c53eff92e93James Kung if (savedInstanceState != null) { 2133e9818e0267619fecebd55095ab26c53eff92e93James Kung mWeekStart = savedInstanceState.getInt(KEY_WEEK_START); 2143e9818e0267619fecebd55095ab26c53eff92e93James Kung mMinYear = savedInstanceState.getInt(KEY_YEAR_START); 2153e9818e0267619fecebd55095ab26c53eff92e93James Kung mMaxYear = savedInstanceState.getInt(KEY_YEAR_END); 216f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung currentView = savedInstanceState.getInt(KEY_CURRENT_VIEW); 2172e00aa34c051111529290cf23c6ba940c2c0c142James Kung listPosition = savedInstanceState.getInt(KEY_LIST_POSITION); 21871492ab60892087f3e989b876b82f5c0249b3b14James Kung listPositionOffset = savedInstanceState.getInt(KEY_LIST_POSITION_OFFSET); 2193e9818e0267619fecebd55095ab26c53eff92e93James Kung } 2203e9818e0267619fecebd55095ab26c53eff92e93James Kung 2212e00aa34c051111529290cf23c6ba940c2c0c142James Kung final Activity activity = getActivity(); 2222e00aa34c051111529290cf23c6ba940c2c0c142James Kung mDayPickerView = new DayPickerView(activity, this); 2232e00aa34c051111529290cf23c6ba940c2c0c142James Kung mYearPickerView = new YearPickerView(activity, this); 2243e9818e0267619fecebd55095ab26c53eff92e93James Kung 225cb3f2522609186db6239ad154af275957118295cSam Blitzstein Resources res = getResources(); 226cb3f2522609186db6239ad154af275957118295cSam Blitzstein mDayPickerDescription = res.getString(R.string.day_picker_description); 227cb3f2522609186db6239ad154af275957118295cSam Blitzstein mSelectDay = res.getString(R.string.select_day); 228cb3f2522609186db6239ad154af275957118295cSam Blitzstein mYearPickerDescription = res.getString(R.string.year_picker_description); 229cb3f2522609186db6239ad154af275957118295cSam Blitzstein mSelectYear = res.getString(R.string.select_year); 230cb3f2522609186db6239ad154af275957118295cSam Blitzstein 231cb3f2522609186db6239ad154af275957118295cSam Blitzstein mAnimator = (AccessibleDateAnimator) view.findViewById(R.id.animator); 2322e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAnimator.addView(mDayPickerView); 2332e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAnimator.addView(mYearPickerView); 234cb3f2522609186db6239ad154af275957118295cSam Blitzstein mAnimator.setDateMillis(mCalendar.getTimeInMillis()); 235f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung // TODO: Replace with animation decided upon by the design team. 236f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung Animation animation = new AlphaAnimation(0.0f, 1.0f); 237f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung animation.setDuration(ANIMATION_DURATION); 238f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mAnimator.setInAnimation(animation); 239f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung // TODO: Replace with animation decided upon by the design team. 240f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung Animation animation2 = new AlphaAnimation(1.0f, 0.0f); 241f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung animation2.setDuration(ANIMATION_DURATION); 242f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mAnimator.setOutAnimation(animation2); 2433e9818e0267619fecebd55095ab26c53eff92e93James Kung 2443e9818e0267619fecebd55095ab26c53eff92e93James Kung mDoneButton = (Button) view.findViewById(R.id.done); 2453e9818e0267619fecebd55095ab26c53eff92e93James Kung mDoneButton.setOnClickListener(new OnClickListener() { 2463e9818e0267619fecebd55095ab26c53eff92e93James Kung 2473e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 2483e9818e0267619fecebd55095ab26c53eff92e93James Kung public void onClick(View v) { 2492e00aa34c051111529290cf23c6ba940c2c0c142James Kung tryVibrate(); 2503e9818e0267619fecebd55095ab26c53eff92e93James Kung if (mCallBack != null) { 2513e9818e0267619fecebd55095ab26c53eff92e93James Kung mCallBack.onDateSet(DatePickerDialog.this, mCalendar.get(Calendar.YEAR), 2523e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH)); 2533e9818e0267619fecebd55095ab26c53eff92e93James Kung } 2543e9818e0267619fecebd55095ab26c53eff92e93James Kung dismiss(); 2553e9818e0267619fecebd55095ab26c53eff92e93James Kung } 2563e9818e0267619fecebd55095ab26c53eff92e93James Kung }); 2573e9818e0267619fecebd55095ab26c53eff92e93James Kung 258cb3f2522609186db6239ad154af275957118295cSam Blitzstein updateDisplay(false); 259f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung setCurrentView(currentView); 2603e9818e0267619fecebd55095ab26c53eff92e93James Kung 2612e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (listPosition != -1) { 2622e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (currentView == MONTH_AND_DAY_VIEW) { 2632e00aa34c051111529290cf23c6ba940c2c0c142James Kung mDayPickerView.postSetSelection(listPosition); 2642e00aa34c051111529290cf23c6ba940c2c0c142James Kung } else if (currentView == YEAR_VIEW) { 26571492ab60892087f3e989b876b82f5c0249b3b14James Kung mYearPickerView.postSetSelectionFromTop(listPosition, listPositionOffset); 2662e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 2672e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 2683fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski 2693fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski mHapticFeedbackController = new HapticFeedbackController(activity); 2703e9818e0267619fecebd55095ab26c53eff92e93James Kung return view; 2713e9818e0267619fecebd55095ab26c53eff92e93James Kung } 2723e9818e0267619fecebd55095ab26c53eff92e93James Kung 2733fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski @Override 2743fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski public void onResume() { 2753fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski super.onResume(); 2763fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski mHapticFeedbackController.start(); 2773fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski } 2783fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski 2793fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski @Override 2803fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski public void onPause() { 2813fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski super.onPause(); 2823fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski mHapticFeedbackController.stop(); 2833fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski } 2843fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski 285f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung private void setCurrentView(final int viewIndex) { 286cb3f2522609186db6239ad154af275957118295cSam Blitzstein long millis = mCalendar.getTimeInMillis(); 287cb3f2522609186db6239ad154af275957118295cSam Blitzstein 288f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung switch (viewIndex) { 289f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung case MONTH_AND_DAY_VIEW: 2902e00aa34c051111529290cf23c6ba940c2c0c142James Kung ObjectAnimator pulseAnimator = Utils.getPulseAnimator(mMonthAndDayView, 0.9f, 2912e00aa34c051111529290cf23c6ba940c2c0c142James Kung 1.05f); 2922e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (mDelayAnimation) { 2932e00aa34c051111529290cf23c6ba940c2c0c142James Kung pulseAnimator.setStartDelay(ANIMATION_DELAY); 2942e00aa34c051111529290cf23c6ba940c2c0c142James Kung mDelayAnimation = false; 2952e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 2962e00aa34c051111529290cf23c6ba940c2c0c142James Kung mDayPickerView.onDateChanged(); 2972e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (mCurrentView != viewIndex) { 2982e00aa34c051111529290cf23c6ba940c2c0c142James Kung mMonthAndDayView.setSelected(true); 2992e00aa34c051111529290cf23c6ba940c2c0c142James Kung mYearView.setSelected(false); 3002e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW); 3012e00aa34c051111529290cf23c6ba940c2c0c142James Kung mCurrentView = viewIndex; 3022e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 3032e00aa34c051111529290cf23c6ba940c2c0c142James Kung pulseAnimator.start(); 304cb3f2522609186db6239ad154af275957118295cSam Blitzstein 305cb3f2522609186db6239ad154af275957118295cSam Blitzstein int flags = DateUtils.FORMAT_SHOW_DATE; 306cb3f2522609186db6239ad154af275957118295cSam Blitzstein String dayString = DateUtils.formatDateTime(getActivity(), millis, flags); 307cb3f2522609186db6239ad154af275957118295cSam Blitzstein mAnimator.setContentDescription(mDayPickerDescription+": "+dayString); 308cb3f2522609186db6239ad154af275957118295cSam Blitzstein Utils.tryAccessibilityAnnounce(mAnimator, mSelectDay); 309f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung break; 310f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung case YEAR_VIEW: 3112e00aa34c051111529290cf23c6ba940c2c0c142James Kung pulseAnimator = Utils.getPulseAnimator(mYearView, 0.85f, 1.1f); 3122e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (mDelayAnimation) { 3132e00aa34c051111529290cf23c6ba940c2c0c142James Kung pulseAnimator.setStartDelay(ANIMATION_DELAY); 3142e00aa34c051111529290cf23c6ba940c2c0c142James Kung mDelayAnimation = false; 3152e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 3162e00aa34c051111529290cf23c6ba940c2c0c142James Kung mYearPickerView.onDateChanged(); 3172e00aa34c051111529290cf23c6ba940c2c0c142James Kung if (mCurrentView != viewIndex) { 3182e00aa34c051111529290cf23c6ba940c2c0c142James Kung mMonthAndDayView.setSelected(false); 3192e00aa34c051111529290cf23c6ba940c2c0c142James Kung mYearView.setSelected(true); 3202e00aa34c051111529290cf23c6ba940c2c0c142James Kung mAnimator.setDisplayedChild(YEAR_VIEW); 3212e00aa34c051111529290cf23c6ba940c2c0c142James Kung mCurrentView = viewIndex; 3222e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 3232e00aa34c051111529290cf23c6ba940c2c0c142James Kung pulseAnimator.start(); 324cb3f2522609186db6239ad154af275957118295cSam Blitzstein 325cb3f2522609186db6239ad154af275957118295cSam Blitzstein CharSequence yearString = YEAR_FORMAT.format(millis); 326cb3f2522609186db6239ad154af275957118295cSam Blitzstein mAnimator.setContentDescription(mYearPickerDescription+": "+yearString); 327cb3f2522609186db6239ad154af275957118295cSam Blitzstein Utils.tryAccessibilityAnnounce(mAnimator, mSelectYear); 328f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung break; 329f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung } 330f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung } 331f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung 332cb3f2522609186db6239ad154af275957118295cSam Blitzstein private void updateDisplay(boolean announce) { 333ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung if (mDayOfWeekView != null) { 334ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung mDayOfWeekView.setText(mCalendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, 335ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung Locale.getDefault()).toUpperCase(Locale.getDefault())); 336ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung } 337cb3f2522609186db6239ad154af275957118295cSam Blitzstein 338f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mSelectedMonthTextView.setText(mCalendar.getDisplayName(Calendar.MONTH, Calendar.SHORT, 3393e9818e0267619fecebd55095ab26c53eff92e93James Kung Locale.getDefault()).toUpperCase(Locale.getDefault())); 340f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung mSelectedDayTextView.setText(DAY_FORMAT.format(mCalendar.getTime())); 3413e9818e0267619fecebd55095ab26c53eff92e93James Kung mYearView.setText(YEAR_FORMAT.format(mCalendar.getTime())); 342cb3f2522609186db6239ad154af275957118295cSam Blitzstein 343cb3f2522609186db6239ad154af275957118295cSam Blitzstein // Accessibility. 344cb3f2522609186db6239ad154af275957118295cSam Blitzstein long millis = mCalendar.getTimeInMillis(); 345cb3f2522609186db6239ad154af275957118295cSam Blitzstein mAnimator.setDateMillis(millis); 346cb3f2522609186db6239ad154af275957118295cSam Blitzstein int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR; 347cb3f2522609186db6239ad154af275957118295cSam Blitzstein String monthAndDayText = DateUtils.formatDateTime(getActivity(), millis, flags); 348cb3f2522609186db6239ad154af275957118295cSam Blitzstein mMonthAndDayView.setContentDescription(monthAndDayText); 349cb3f2522609186db6239ad154af275957118295cSam Blitzstein 350cb3f2522609186db6239ad154af275957118295cSam Blitzstein if (announce) { 351cb3f2522609186db6239ad154af275957118295cSam Blitzstein flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR; 352cb3f2522609186db6239ad154af275957118295cSam Blitzstein String fullDateText = DateUtils.formatDateTime(getActivity(), millis, flags); 353cb3f2522609186db6239ad154af275957118295cSam Blitzstein Utils.tryAccessibilityAnnounce(mAnimator, fullDateText); 354cb3f2522609186db6239ad154af275957118295cSam Blitzstein } 3553e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3563e9818e0267619fecebd55095ab26c53eff92e93James Kung 3573e9818e0267619fecebd55095ab26c53eff92e93James Kung public void setFirstDayOfWeek(int startOfWeek) { 3583e9818e0267619fecebd55095ab26c53eff92e93James Kung if (startOfWeek < Calendar.SUNDAY || startOfWeek > Calendar.SATURDAY) { 3593e9818e0267619fecebd55095ab26c53eff92e93James Kung throw new IllegalArgumentException("Value must be between Calendar.SUNDAY and " + 3603e9818e0267619fecebd55095ab26c53eff92e93James Kung "Calendar.SATURDAY"); 3613e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3623e9818e0267619fecebd55095ab26c53eff92e93James Kung mWeekStart = startOfWeek; 3633e9818e0267619fecebd55095ab26c53eff92e93James Kung if (mDayPickerView != null) { 3643e9818e0267619fecebd55095ab26c53eff92e93James Kung mDayPickerView.onChange(); 3653e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3663e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3673e9818e0267619fecebd55095ab26c53eff92e93James Kung 3683e9818e0267619fecebd55095ab26c53eff92e93James Kung public void setYearRange(int startYear, int endYear) { 3693e9818e0267619fecebd55095ab26c53eff92e93James Kung if (endYear <= startYear) { 3703e9818e0267619fecebd55095ab26c53eff92e93James Kung throw new IllegalArgumentException("Year end must be larger than year start"); 3713e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3723e9818e0267619fecebd55095ab26c53eff92e93James Kung mMinYear = startYear; 3733e9818e0267619fecebd55095ab26c53eff92e93James Kung mMaxYear = endYear; 3743e9818e0267619fecebd55095ab26c53eff92e93James Kung if (mDayPickerView != null) { 3753e9818e0267619fecebd55095ab26c53eff92e93James Kung mDayPickerView.onChange(); 3763e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3773e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3783e9818e0267619fecebd55095ab26c53eff92e93James Kung 3793e9818e0267619fecebd55095ab26c53eff92e93James Kung public void setOnDateSetListener(OnDateSetListener listener) { 3803e9818e0267619fecebd55095ab26c53eff92e93James Kung mCallBack = listener; 3813e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3823e9818e0267619fecebd55095ab26c53eff92e93James Kung 3833e9818e0267619fecebd55095ab26c53eff92e93James Kung // If the newly selected month / year does not contain the currently selected day number, 3843e9818e0267619fecebd55095ab26c53eff92e93James Kung // change the selected day number to the last day of the selected month or year. 3853e9818e0267619fecebd55095ab26c53eff92e93James Kung // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30 3863e9818e0267619fecebd55095ab26c53eff92e93James Kung // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013 3873e9818e0267619fecebd55095ab26c53eff92e93James Kung private void adjustDayInMonthIfNeeded(int month, int year) { 3883e9818e0267619fecebd55095ab26c53eff92e93James Kung int day = mCalendar.get(Calendar.DAY_OF_MONTH); 3893e9818e0267619fecebd55095ab26c53eff92e93James Kung int daysInMonth = Utils.getDaysInMonth(month, year); 3903e9818e0267619fecebd55095ab26c53eff92e93James Kung if (day > daysInMonth) { 3913e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.DAY_OF_MONTH, daysInMonth); 3923e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3933e9818e0267619fecebd55095ab26c53eff92e93James Kung } 3943e9818e0267619fecebd55095ab26c53eff92e93James Kung 3953e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 3963e9818e0267619fecebd55095ab26c53eff92e93James Kung public void onClick(View v) { 3972e00aa34c051111529290cf23c6ba940c2c0c142James Kung tryVibrate(); 3983e9818e0267619fecebd55095ab26c53eff92e93James Kung if (v.getId() == R.id.date_picker_year) { 399f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung setCurrentView(YEAR_VIEW); 400f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung } else if (v.getId() == R.id.date_picker_month_and_day) { 401f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung setCurrentView(MONTH_AND_DAY_VIEW); 4023e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4033e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4043e9818e0267619fecebd55095ab26c53eff92e93James Kung 4053e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 4062e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onYearSelected(int year) { 4073e9818e0267619fecebd55095ab26c53eff92e93James Kung adjustDayInMonthIfNeeded(mCalendar.get(Calendar.MONTH), year); 4083e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.YEAR, year); 4092e00aa34c051111529290cf23c6ba940c2c0c142James Kung updatePickers(); 410f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung setCurrentView(MONTH_AND_DAY_VIEW); 411cb3f2522609186db6239ad154af275957118295cSam Blitzstein updateDisplay(true); 4123e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4133e9818e0267619fecebd55095ab26c53eff92e93James Kung 4143e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 4152e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void onDayOfMonthSelected(int year, int month, int day) { 4163e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.YEAR, year); 4173e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.MONTH, month); 4183e9818e0267619fecebd55095ab26c53eff92e93James Kung mCalendar.set(Calendar.DAY_OF_MONTH, day); 4192e00aa34c051111529290cf23c6ba940c2c0c142James Kung updatePickers(); 420cb3f2522609186db6239ad154af275957118295cSam Blitzstein updateDisplay(true); 4213e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4223e9818e0267619fecebd55095ab26c53eff92e93James Kung 4232e00aa34c051111529290cf23c6ba940c2c0c142James Kung private void updatePickers() { 4242e00aa34c051111529290cf23c6ba940c2c0c142James Kung Iterator<OnDateChangedListener> iterator = mListeners.iterator(); 4252e00aa34c051111529290cf23c6ba940c2c0c142James Kung while (iterator.hasNext()) { 4262e00aa34c051111529290cf23c6ba940c2c0c142James Kung iterator.next().onDateChanged(); 4272e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 4282e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 4292e00aa34c051111529290cf23c6ba940c2c0c142James Kung 4303e9818e0267619fecebd55095ab26c53eff92e93James Kung 4313e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 4323e9818e0267619fecebd55095ab26c53eff92e93James Kung public CalendarDay getSelectedDay() { 4333e9818e0267619fecebd55095ab26c53eff92e93James Kung return new CalendarDay(mCalendar); 4343e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4353e9818e0267619fecebd55095ab26c53eff92e93James Kung 4363e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 4373e9818e0267619fecebd55095ab26c53eff92e93James Kung public int getMinYear() { 4383e9818e0267619fecebd55095ab26c53eff92e93James Kung return mMinYear; 4393e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4403e9818e0267619fecebd55095ab26c53eff92e93James Kung 4413e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 4423e9818e0267619fecebd55095ab26c53eff92e93James Kung public int getMaxYear() { 4433e9818e0267619fecebd55095ab26c53eff92e93James Kung return mMaxYear; 4443e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4453e9818e0267619fecebd55095ab26c53eff92e93James Kung 4463e9818e0267619fecebd55095ab26c53eff92e93James Kung @Override 4473e9818e0267619fecebd55095ab26c53eff92e93James Kung public int getFirstDayOfWeek() { 4483e9818e0267619fecebd55095ab26c53eff92e93James Kung return mWeekStart; 4493e9818e0267619fecebd55095ab26c53eff92e93James Kung } 4502e00aa34c051111529290cf23c6ba940c2c0c142James Kung 4512e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 4522e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void registerOnDateChangedListener(OnDateChangedListener listener) { 4532e00aa34c051111529290cf23c6ba940c2c0c142James Kung mListeners.add(listener); 4542e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 4552e00aa34c051111529290cf23c6ba940c2c0c142James Kung 4562e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 4572e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void unregisterOnDateChangedListener(OnDateChangedListener listener) { 4582e00aa34c051111529290cf23c6ba940c2c0c142James Kung mListeners.remove(listener); 4592e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 4602e00aa34c051111529290cf23c6ba940c2c0c142James Kung 4612e00aa34c051111529290cf23c6ba940c2c0c142James Kung @Override 4622e00aa34c051111529290cf23c6ba940c2c0c142James Kung public void tryVibrate() { 4633fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski mHapticFeedbackController.tryVibrate(); 4642e00aa34c051111529290cf23c6ba940c2c0c142James Kung } 4653e9818e0267619fecebd55095ab26c53eff92e93James Kung} 466