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;
41e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport com.android.datetimepicker.date.MonthAdapter.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;
1007c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    private Calendar mMinDate;
1017c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    private Calendar mMaxDate;
1023e9818e0267619fecebd55095ab26c53eff92e93James Kung
1033fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    private HapticFeedbackController mHapticFeedbackController;
1042e00aa34c051111529290cf23c6ba940c2c0c142James Kung
1052e00aa34c051111529290cf23c6ba940c2c0c142James Kung    private boolean mDelayAnimation = true;
1063e9818e0267619fecebd55095ab26c53eff92e93James Kung
107cb3f2522609186db6239ad154af275957118295cSam Blitzstein    // Accessibility strings.
108cb3f2522609186db6239ad154af275957118295cSam Blitzstein    private String mDayPickerDescription;
109cb3f2522609186db6239ad154af275957118295cSam Blitzstein    private String mSelectDay;
110cb3f2522609186db6239ad154af275957118295cSam Blitzstein    private String mYearPickerDescription;
111cb3f2522609186db6239ad154af275957118295cSam Blitzstein    private String mSelectYear;
112cb3f2522609186db6239ad154af275957118295cSam Blitzstein
1133e9818e0267619fecebd55095ab26c53eff92e93James Kung    /**
1143e9818e0267619fecebd55095ab26c53eff92e93James Kung     * The callback used to indicate the user is done filling in the date.
1153e9818e0267619fecebd55095ab26c53eff92e93James Kung     */
1163e9818e0267619fecebd55095ab26c53eff92e93James Kung    public interface OnDateSetListener {
1173e9818e0267619fecebd55095ab26c53eff92e93James Kung
1183e9818e0267619fecebd55095ab26c53eff92e93James Kung        /**
1193e9818e0267619fecebd55095ab26c53eff92e93James Kung         * @param view The view associated with this listener.
1203e9818e0267619fecebd55095ab26c53eff92e93James Kung         * @param year The year that was set.
1213e9818e0267619fecebd55095ab26c53eff92e93James Kung         * @param monthOfYear The month that was set (0-11) for compatibility
1223e9818e0267619fecebd55095ab26c53eff92e93James Kung         *            with {@link java.util.Calendar}.
1233e9818e0267619fecebd55095ab26c53eff92e93James Kung         * @param dayOfMonth The day of the month that was set.
1243e9818e0267619fecebd55095ab26c53eff92e93James Kung         */
1253e9818e0267619fecebd55095ab26c53eff92e93James Kung        void onDateSet(DatePickerDialog dialog, int year, int monthOfYear, int dayOfMonth);
1263e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
1273e9818e0267619fecebd55095ab26c53eff92e93James Kung
1282e00aa34c051111529290cf23c6ba940c2c0c142James Kung    /**
1292e00aa34c051111529290cf23c6ba940c2c0c142James Kung     * The callback used to notify other date picker components of a change in selected date.
1302e00aa34c051111529290cf23c6ba940c2c0c142James Kung     */
131385d36f15358e7d035b2e89e395588eb7952ebc2James Kung    public interface OnDateChangedListener {
1322e00aa34c051111529290cf23c6ba940c2c0c142James Kung
1332e00aa34c051111529290cf23c6ba940c2c0c142James Kung        public void onDateChanged();
1342e00aa34c051111529290cf23c6ba940c2c0c142James Kung    }
1352e00aa34c051111529290cf23c6ba940c2c0c142James Kung
1362e00aa34c051111529290cf23c6ba940c2c0c142James Kung
1373e9818e0267619fecebd55095ab26c53eff92e93James Kung    public DatePickerDialog() {
1383e9818e0267619fecebd55095ab26c53eff92e93James Kung        // Empty constructor required for dialog fragment.
1393e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
1403e9818e0267619fecebd55095ab26c53eff92e93James Kung
1413e9818e0267619fecebd55095ab26c53eff92e93James Kung    /**
1423e9818e0267619fecebd55095ab26c53eff92e93James Kung     * @param callBack How the parent is notified that the date is set.
1433e9818e0267619fecebd55095ab26c53eff92e93James Kung     * @param year The initial year of the dialog.
1443e9818e0267619fecebd55095ab26c53eff92e93James Kung     * @param monthOfYear The initial month of the dialog.
1453e9818e0267619fecebd55095ab26c53eff92e93James Kung     * @param dayOfMonth The initial day of the dialog.
1463e9818e0267619fecebd55095ab26c53eff92e93James Kung     */
1473e9818e0267619fecebd55095ab26c53eff92e93James Kung    public static DatePickerDialog newInstance(OnDateSetListener callBack, int year,
1483e9818e0267619fecebd55095ab26c53eff92e93James Kung            int monthOfYear,
1493e9818e0267619fecebd55095ab26c53eff92e93James Kung            int dayOfMonth) {
1503e9818e0267619fecebd55095ab26c53eff92e93James Kung        DatePickerDialog ret = new DatePickerDialog();
1513e9818e0267619fecebd55095ab26c53eff92e93James Kung        ret.initialize(callBack, year, monthOfYear, dayOfMonth);
1523e9818e0267619fecebd55095ab26c53eff92e93James Kung        return ret;
1533e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
1543e9818e0267619fecebd55095ab26c53eff92e93James Kung
1553e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void initialize(OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
1563e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCallBack = callBack;
1573e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.YEAR, year);
1583e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.MONTH, monthOfYear);
1593e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
1603e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
1613e9818e0267619fecebd55095ab26c53eff92e93James Kung
1623e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
1633e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void onCreate(Bundle savedInstanceState) {
1643e9818e0267619fecebd55095ab26c53eff92e93James Kung        super.onCreate(savedInstanceState);
1652e00aa34c051111529290cf23c6ba940c2c0c142James Kung        final Activity activity = getActivity();
1662e00aa34c051111529290cf23c6ba940c2c0c142James Kung        activity.getWindow().setSoftInputMode(
167f4d8e7a2271df7025f61d5ed086455a00b3fd325James Kung                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
1683e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (savedInstanceState != null) {
1693e9818e0267619fecebd55095ab26c53eff92e93James Kung            mCalendar.set(Calendar.YEAR, savedInstanceState.getInt(KEY_SELECTED_YEAR));
1703e9818e0267619fecebd55095ab26c53eff92e93James Kung            mCalendar.set(Calendar.MONTH, savedInstanceState.getInt(KEY_SELECTED_MONTH));
1713e9818e0267619fecebd55095ab26c53eff92e93James Kung            mCalendar.set(Calendar.DAY_OF_MONTH, savedInstanceState.getInt(KEY_SELECTED_DAY));
1723e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
1733e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
1743e9818e0267619fecebd55095ab26c53eff92e93James Kung
1753e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
1763e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void onSaveInstanceState(Bundle outState) {
1773e9818e0267619fecebd55095ab26c53eff92e93James Kung        super.onSaveInstanceState(outState);
1783e9818e0267619fecebd55095ab26c53eff92e93James Kung        outState.putInt(KEY_SELECTED_YEAR, mCalendar.get(Calendar.YEAR));
1793e9818e0267619fecebd55095ab26c53eff92e93James Kung        outState.putInt(KEY_SELECTED_MONTH, mCalendar.get(Calendar.MONTH));
1803e9818e0267619fecebd55095ab26c53eff92e93James Kung        outState.putInt(KEY_SELECTED_DAY, mCalendar.get(Calendar.DAY_OF_MONTH));
1813e9818e0267619fecebd55095ab26c53eff92e93James Kung        outState.putInt(KEY_WEEK_START, mWeekStart);
1823e9818e0267619fecebd55095ab26c53eff92e93James Kung        outState.putInt(KEY_YEAR_START, mMinYear);
1833e9818e0267619fecebd55095ab26c53eff92e93James Kung        outState.putInt(KEY_YEAR_END, mMaxYear);
184f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        outState.putInt(KEY_CURRENT_VIEW, mCurrentView);
1852e00aa34c051111529290cf23c6ba940c2c0c142James Kung        int listPosition = -1;
1862e00aa34c051111529290cf23c6ba940c2c0c142James Kung        if (mCurrentView == MONTH_AND_DAY_VIEW) {
1872e00aa34c051111529290cf23c6ba940c2c0c142James Kung            listPosition = mDayPickerView.getMostVisiblePosition();
1882e00aa34c051111529290cf23c6ba940c2c0c142James Kung        } else if (mCurrentView == YEAR_VIEW) {
1892e00aa34c051111529290cf23c6ba940c2c0c142James Kung            listPosition = mYearPickerView.getFirstVisiblePosition();
19071492ab60892087f3e989b876b82f5c0249b3b14James Kung            outState.putInt(KEY_LIST_POSITION_OFFSET, mYearPickerView.getFirstPositionOffset());
1912e00aa34c051111529290cf23c6ba940c2c0c142James Kung        }
1922e00aa34c051111529290cf23c6ba940c2c0c142James Kung        outState.putInt(KEY_LIST_POSITION, listPosition);
1933e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
1943e9818e0267619fecebd55095ab26c53eff92e93James Kung
1953e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
1963e9818e0267619fecebd55095ab26c53eff92e93James Kung    public View onCreateView(LayoutInflater inflater, ViewGroup container,
1973e9818e0267619fecebd55095ab26c53eff92e93James Kung            Bundle savedInstanceState) {
1983e9818e0267619fecebd55095ab26c53eff92e93James Kung        Log.d(TAG, "onCreateView: ");
1993e9818e0267619fecebd55095ab26c53eff92e93James Kung        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
2003e9818e0267619fecebd55095ab26c53eff92e93James Kung
2013e9818e0267619fecebd55095ab26c53eff92e93James Kung        View view = inflater.inflate(R.layout.date_picker_dialog, null);
2023e9818e0267619fecebd55095ab26c53eff92e93James Kung
2033e9818e0267619fecebd55095ab26c53eff92e93James Kung        mDayOfWeekView = (TextView) view.findViewById(R.id.date_picker_header);
204f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mMonthAndDayView = (LinearLayout) view.findViewById(R.id.date_picker_month_and_day);
205f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mMonthAndDayView.setOnClickListener(this);
206f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mSelectedMonthTextView = (TextView) view.findViewById(R.id.date_picker_month);
207f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mSelectedDayTextView = (TextView) view.findViewById(R.id.date_picker_day);
2083e9818e0267619fecebd55095ab26c53eff92e93James Kung        mYearView = (TextView) view.findViewById(R.id.date_picker_year);
2093e9818e0267619fecebd55095ab26c53eff92e93James Kung        mYearView.setOnClickListener(this);
2103e9818e0267619fecebd55095ab26c53eff92e93James Kung
2112e00aa34c051111529290cf23c6ba940c2c0c142James Kung        int listPosition = -1;
21271492ab60892087f3e989b876b82f5c0249b3b14James Kung        int listPositionOffset = 0;
213f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        int currentView = MONTH_AND_DAY_VIEW;
2143e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (savedInstanceState != null) {
2153e9818e0267619fecebd55095ab26c53eff92e93James Kung            mWeekStart = savedInstanceState.getInt(KEY_WEEK_START);
2163e9818e0267619fecebd55095ab26c53eff92e93James Kung            mMinYear = savedInstanceState.getInt(KEY_YEAR_START);
2173e9818e0267619fecebd55095ab26c53eff92e93James Kung            mMaxYear = savedInstanceState.getInt(KEY_YEAR_END);
218f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung            currentView = savedInstanceState.getInt(KEY_CURRENT_VIEW);
2192e00aa34c051111529290cf23c6ba940c2c0c142James Kung            listPosition = savedInstanceState.getInt(KEY_LIST_POSITION);
22071492ab60892087f3e989b876b82f5c0249b3b14James Kung            listPositionOffset = savedInstanceState.getInt(KEY_LIST_POSITION_OFFSET);
2213e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
2223e9818e0267619fecebd55095ab26c53eff92e93James Kung
2232e00aa34c051111529290cf23c6ba940c2c0c142James Kung        final Activity activity = getActivity();
224e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung        mDayPickerView = new SimpleDayPickerView(activity, this);
2252e00aa34c051111529290cf23c6ba940c2c0c142James Kung        mYearPickerView = new YearPickerView(activity, this);
2263e9818e0267619fecebd55095ab26c53eff92e93James Kung
227cb3f2522609186db6239ad154af275957118295cSam Blitzstein        Resources res = getResources();
228cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mDayPickerDescription = res.getString(R.string.day_picker_description);
229cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mSelectDay = res.getString(R.string.select_day);
230cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mYearPickerDescription = res.getString(R.string.year_picker_description);
231cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mSelectYear = res.getString(R.string.select_year);
232cb3f2522609186db6239ad154af275957118295cSam Blitzstein
233cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mAnimator = (AccessibleDateAnimator) view.findViewById(R.id.animator);
2342e00aa34c051111529290cf23c6ba940c2c0c142James Kung        mAnimator.addView(mDayPickerView);
2352e00aa34c051111529290cf23c6ba940c2c0c142James Kung        mAnimator.addView(mYearPickerView);
236cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mAnimator.setDateMillis(mCalendar.getTimeInMillis());
237f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        // TODO: Replace with animation decided upon by the design team.
238f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        Animation animation = new AlphaAnimation(0.0f, 1.0f);
239f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        animation.setDuration(ANIMATION_DURATION);
240f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mAnimator.setInAnimation(animation);
241f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        // TODO: Replace with animation decided upon by the design team.
242f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        Animation animation2 = new AlphaAnimation(1.0f, 0.0f);
243f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        animation2.setDuration(ANIMATION_DURATION);
244f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mAnimator.setOutAnimation(animation2);
2453e9818e0267619fecebd55095ab26c53eff92e93James Kung
2463e9818e0267619fecebd55095ab26c53eff92e93James Kung        mDoneButton = (Button) view.findViewById(R.id.done);
2473e9818e0267619fecebd55095ab26c53eff92e93James Kung        mDoneButton.setOnClickListener(new OnClickListener() {
2483e9818e0267619fecebd55095ab26c53eff92e93James Kung
2493e9818e0267619fecebd55095ab26c53eff92e93James Kung            @Override
2503e9818e0267619fecebd55095ab26c53eff92e93James Kung            public void onClick(View v) {
2512e00aa34c051111529290cf23c6ba940c2c0c142James Kung                tryVibrate();
2523e9818e0267619fecebd55095ab26c53eff92e93James Kung                if (mCallBack != null) {
2533e9818e0267619fecebd55095ab26c53eff92e93James Kung                    mCallBack.onDateSet(DatePickerDialog.this, mCalendar.get(Calendar.YEAR),
2543e9818e0267619fecebd55095ab26c53eff92e93James Kung                            mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH));
2553e9818e0267619fecebd55095ab26c53eff92e93James Kung                }
2563e9818e0267619fecebd55095ab26c53eff92e93James Kung                dismiss();
2573e9818e0267619fecebd55095ab26c53eff92e93James Kung            }
2583e9818e0267619fecebd55095ab26c53eff92e93James Kung        });
2593e9818e0267619fecebd55095ab26c53eff92e93James Kung
260cb3f2522609186db6239ad154af275957118295cSam Blitzstein        updateDisplay(false);
261f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        setCurrentView(currentView);
2623e9818e0267619fecebd55095ab26c53eff92e93James Kung
2632e00aa34c051111529290cf23c6ba940c2c0c142James Kung        if (listPosition != -1) {
2642e00aa34c051111529290cf23c6ba940c2c0c142James Kung            if (currentView == MONTH_AND_DAY_VIEW) {
2652e00aa34c051111529290cf23c6ba940c2c0c142James Kung                mDayPickerView.postSetSelection(listPosition);
2662e00aa34c051111529290cf23c6ba940c2c0c142James Kung            } else if (currentView == YEAR_VIEW) {
26771492ab60892087f3e989b876b82f5c0249b3b14James Kung                mYearPickerView.postSetSelectionFromTop(listPosition, listPositionOffset);
2682e00aa34c051111529290cf23c6ba940c2c0c142James Kung            }
2692e00aa34c051111529290cf23c6ba940c2c0c142James Kung        }
2703fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski
2713fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski        mHapticFeedbackController = new HapticFeedbackController(activity);
2723e9818e0267619fecebd55095ab26c53eff92e93James Kung        return view;
2733e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
2743e9818e0267619fecebd55095ab26c53eff92e93James Kung
2753fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    @Override
2763fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    public void onResume() {
2773fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski        super.onResume();
2783fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski        mHapticFeedbackController.start();
2793fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    }
2803fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski
2813fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    @Override
2823fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    public void onPause() {
2833fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski        super.onPause();
2843fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski        mHapticFeedbackController.stop();
2853fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski    }
2863fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski
287f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung    private void setCurrentView(final int viewIndex) {
288cb3f2522609186db6239ad154af275957118295cSam Blitzstein        long millis = mCalendar.getTimeInMillis();
289cb3f2522609186db6239ad154af275957118295cSam Blitzstein
290f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        switch (viewIndex) {
291f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung            case MONTH_AND_DAY_VIEW:
2922e00aa34c051111529290cf23c6ba940c2c0c142James Kung                ObjectAnimator pulseAnimator = Utils.getPulseAnimator(mMonthAndDayView, 0.9f,
2932e00aa34c051111529290cf23c6ba940c2c0c142James Kung                        1.05f);
2942e00aa34c051111529290cf23c6ba940c2c0c142James Kung                if (mDelayAnimation) {
2952e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    pulseAnimator.setStartDelay(ANIMATION_DELAY);
2962e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mDelayAnimation = false;
2972e00aa34c051111529290cf23c6ba940c2c0c142James Kung                }
2982e00aa34c051111529290cf23c6ba940c2c0c142James Kung                mDayPickerView.onDateChanged();
2992e00aa34c051111529290cf23c6ba940c2c0c142James Kung                if (mCurrentView != viewIndex) {
3002e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mMonthAndDayView.setSelected(true);
3012e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mYearView.setSelected(false);
3022e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW);
3032e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mCurrentView = viewIndex;
3042e00aa34c051111529290cf23c6ba940c2c0c142James Kung                }
3052e00aa34c051111529290cf23c6ba940c2c0c142James Kung                pulseAnimator.start();
306cb3f2522609186db6239ad154af275957118295cSam Blitzstein
307cb3f2522609186db6239ad154af275957118295cSam Blitzstein                int flags = DateUtils.FORMAT_SHOW_DATE;
308cb3f2522609186db6239ad154af275957118295cSam Blitzstein                String dayString = DateUtils.formatDateTime(getActivity(), millis, flags);
309cb3f2522609186db6239ad154af275957118295cSam Blitzstein                mAnimator.setContentDescription(mDayPickerDescription+": "+dayString);
310cb3f2522609186db6239ad154af275957118295cSam Blitzstein                Utils.tryAccessibilityAnnounce(mAnimator, mSelectDay);
311f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung                break;
312f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung            case YEAR_VIEW:
3132e00aa34c051111529290cf23c6ba940c2c0c142James Kung                pulseAnimator = Utils.getPulseAnimator(mYearView, 0.85f, 1.1f);
3142e00aa34c051111529290cf23c6ba940c2c0c142James Kung                if (mDelayAnimation) {
3152e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    pulseAnimator.setStartDelay(ANIMATION_DELAY);
3162e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mDelayAnimation = false;
3172e00aa34c051111529290cf23c6ba940c2c0c142James Kung                }
3182e00aa34c051111529290cf23c6ba940c2c0c142James Kung                mYearPickerView.onDateChanged();
3192e00aa34c051111529290cf23c6ba940c2c0c142James Kung                if (mCurrentView != viewIndex) {
3202e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mMonthAndDayView.setSelected(false);
3212e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mYearView.setSelected(true);
3222e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mAnimator.setDisplayedChild(YEAR_VIEW);
3232e00aa34c051111529290cf23c6ba940c2c0c142James Kung                    mCurrentView = viewIndex;
3242e00aa34c051111529290cf23c6ba940c2c0c142James Kung                }
3252e00aa34c051111529290cf23c6ba940c2c0c142James Kung                pulseAnimator.start();
326cb3f2522609186db6239ad154af275957118295cSam Blitzstein
327cb3f2522609186db6239ad154af275957118295cSam Blitzstein                CharSequence yearString = YEAR_FORMAT.format(millis);
328cb3f2522609186db6239ad154af275957118295cSam Blitzstein                mAnimator.setContentDescription(mYearPickerDescription+": "+yearString);
329cb3f2522609186db6239ad154af275957118295cSam Blitzstein                Utils.tryAccessibilityAnnounce(mAnimator, mSelectYear);
330f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung                break;
331f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        }
332f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung    }
333f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung
334cb3f2522609186db6239ad154af275957118295cSam Blitzstein    private void updateDisplay(boolean announce) {
335ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung        if (mDayOfWeekView != null) {
336ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung            mDayOfWeekView.setText(mCalendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG,
337ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung                    Locale.getDefault()).toUpperCase(Locale.getDefault()));
338ddf949ac36c2a3b7a45918814d2c7bc57480aa9bJames Kung        }
339cb3f2522609186db6239ad154af275957118295cSam Blitzstein
340f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mSelectedMonthTextView.setText(mCalendar.getDisplayName(Calendar.MONTH, Calendar.SHORT,
3413e9818e0267619fecebd55095ab26c53eff92e93James Kung                Locale.getDefault()).toUpperCase(Locale.getDefault()));
342f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        mSelectedDayTextView.setText(DAY_FORMAT.format(mCalendar.getTime()));
3433e9818e0267619fecebd55095ab26c53eff92e93James Kung        mYearView.setText(YEAR_FORMAT.format(mCalendar.getTime()));
344cb3f2522609186db6239ad154af275957118295cSam Blitzstein
345cb3f2522609186db6239ad154af275957118295cSam Blitzstein        // Accessibility.
346cb3f2522609186db6239ad154af275957118295cSam Blitzstein        long millis = mCalendar.getTimeInMillis();
347cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mAnimator.setDateMillis(millis);
348cb3f2522609186db6239ad154af275957118295cSam Blitzstein        int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
349cb3f2522609186db6239ad154af275957118295cSam Blitzstein        String monthAndDayText = DateUtils.formatDateTime(getActivity(), millis, flags);
350cb3f2522609186db6239ad154af275957118295cSam Blitzstein        mMonthAndDayView.setContentDescription(monthAndDayText);
351cb3f2522609186db6239ad154af275957118295cSam Blitzstein
352cb3f2522609186db6239ad154af275957118295cSam Blitzstein        if (announce) {
353cb3f2522609186db6239ad154af275957118295cSam Blitzstein            flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
354cb3f2522609186db6239ad154af275957118295cSam Blitzstein            String fullDateText = DateUtils.formatDateTime(getActivity(), millis, flags);
355cb3f2522609186db6239ad154af275957118295cSam Blitzstein            Utils.tryAccessibilityAnnounce(mAnimator, fullDateText);
356cb3f2522609186db6239ad154af275957118295cSam Blitzstein        }
3573e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
3583e9818e0267619fecebd55095ab26c53eff92e93James Kung
3593e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void setFirstDayOfWeek(int startOfWeek) {
3603e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (startOfWeek < Calendar.SUNDAY || startOfWeek > Calendar.SATURDAY) {
3613e9818e0267619fecebd55095ab26c53eff92e93James Kung            throw new IllegalArgumentException("Value must be between Calendar.SUNDAY and " +
3623e9818e0267619fecebd55095ab26c53eff92e93James Kung                    "Calendar.SATURDAY");
3633e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
3643e9818e0267619fecebd55095ab26c53eff92e93James Kung        mWeekStart = startOfWeek;
3653e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (mDayPickerView != null) {
3663e9818e0267619fecebd55095ab26c53eff92e93James Kung            mDayPickerView.onChange();
3673e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
3683e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
3693e9818e0267619fecebd55095ab26c53eff92e93James Kung
3703e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void setYearRange(int startYear, int endYear) {
3713e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (endYear <= startYear) {
3723e9818e0267619fecebd55095ab26c53eff92e93James Kung            throw new IllegalArgumentException("Year end must be larger than year start");
3733e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
3743e9818e0267619fecebd55095ab26c53eff92e93James Kung        mMinYear = startYear;
3753e9818e0267619fecebd55095ab26c53eff92e93James Kung        mMaxYear = endYear;
3763e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (mDayPickerView != null) {
3773e9818e0267619fecebd55095ab26c53eff92e93James Kung            mDayPickerView.onChange();
3783e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
3793e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
3803e9818e0267619fecebd55095ab26c53eff92e93James Kung
3817c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    /**
3827c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * Sets the minimal date supported by this DatePicker. Dates before (but not including) the
3837c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * specified date will be disallowed from being selected.
3847c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * @param calendar a Calendar object set to the year, month, day desired as the mindate.
3857c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     */
3867c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    public void setMinDate(Calendar calendar) {
3877c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        mMinDate = calendar;
3887c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein
3897c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        if (mDayPickerView != null) {
3907c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein            mDayPickerView.onChange();
3917c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        }
3927c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    }
3937c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein
3947c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    /**
3957c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * @return The minimal date supported by this DatePicker. Null if it has not been set.
3967c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     */
3977c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    @Override
3987c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    public Calendar getMinDate() {
3997c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        return mMinDate;
4007c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    }
4017c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein
4027c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    /**
4037c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * Sets the minimal date supported by this DatePicker. Dates after (but not including) the
4047c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * specified date will be disallowed from being selected.
4057c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * @param calendar a Calendar object set to the year, month, day desired as the maxdate.
4067c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     */
4077c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    public void setMaxDate(Calendar calendar) {
4087c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        mMaxDate = calendar;
4097c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein
4107c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        if (mDayPickerView != null) {
4117c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein            mDayPickerView.onChange();
4127c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        }
4137c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    }
4147c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein
4157c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    /**
4167c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     * @return The maximal date supported by this DatePicker. Null if it has not been set.
4177c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein     */
4187c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    @Override
4197c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    public Calendar getMaxDate() {
4207c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein        return mMaxDate;
4217c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein    }
4227c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein
4233e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void setOnDateSetListener(OnDateSetListener listener) {
4243e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCallBack = listener;
4253e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4263e9818e0267619fecebd55095ab26c53eff92e93James Kung
4273e9818e0267619fecebd55095ab26c53eff92e93James Kung    // If the newly selected month / year does not contain the currently selected day number,
4283e9818e0267619fecebd55095ab26c53eff92e93James Kung    // change the selected day number to the last day of the selected month or year.
4293e9818e0267619fecebd55095ab26c53eff92e93James Kung    //      e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
4303e9818e0267619fecebd55095ab26c53eff92e93James Kung    //      e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
4313e9818e0267619fecebd55095ab26c53eff92e93James Kung    private void adjustDayInMonthIfNeeded(int month, int year) {
4323e9818e0267619fecebd55095ab26c53eff92e93James Kung        int day = mCalendar.get(Calendar.DAY_OF_MONTH);
4333e9818e0267619fecebd55095ab26c53eff92e93James Kung        int daysInMonth = Utils.getDaysInMonth(month, year);
4343e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (day > daysInMonth) {
4353e9818e0267619fecebd55095ab26c53eff92e93James Kung            mCalendar.set(Calendar.DAY_OF_MONTH, daysInMonth);
4363e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
4373e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4383e9818e0267619fecebd55095ab26c53eff92e93James Kung
4393e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4403e9818e0267619fecebd55095ab26c53eff92e93James Kung    public void onClick(View v) {
4412e00aa34c051111529290cf23c6ba940c2c0c142James Kung        tryVibrate();
4423e9818e0267619fecebd55095ab26c53eff92e93James Kung        if (v.getId() == R.id.date_picker_year) {
443f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung            setCurrentView(YEAR_VIEW);
444f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        } else if (v.getId() == R.id.date_picker_month_and_day) {
445f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung            setCurrentView(MONTH_AND_DAY_VIEW);
4463e9818e0267619fecebd55095ab26c53eff92e93James Kung        }
4473e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4483e9818e0267619fecebd55095ab26c53eff92e93James Kung
4493e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4502e00aa34c051111529290cf23c6ba940c2c0c142James Kung    public void onYearSelected(int year) {
4513e9818e0267619fecebd55095ab26c53eff92e93James Kung        adjustDayInMonthIfNeeded(mCalendar.get(Calendar.MONTH), year);
4523e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.YEAR, year);
4532e00aa34c051111529290cf23c6ba940c2c0c142James Kung        updatePickers();
454f6de1f602ffac70987ebc9fc5e887494a23ddd35James Kung        setCurrentView(MONTH_AND_DAY_VIEW);
455cb3f2522609186db6239ad154af275957118295cSam Blitzstein        updateDisplay(true);
4563e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4573e9818e0267619fecebd55095ab26c53eff92e93James Kung
4583e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4592e00aa34c051111529290cf23c6ba940c2c0c142James Kung    public void onDayOfMonthSelected(int year, int month, int day) {
4603e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.YEAR, year);
4613e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.MONTH, month);
4623e9818e0267619fecebd55095ab26c53eff92e93James Kung        mCalendar.set(Calendar.DAY_OF_MONTH, day);
4632e00aa34c051111529290cf23c6ba940c2c0c142James Kung        updatePickers();
464cb3f2522609186db6239ad154af275957118295cSam Blitzstein        updateDisplay(true);
4653e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4663e9818e0267619fecebd55095ab26c53eff92e93James Kung
4672e00aa34c051111529290cf23c6ba940c2c0c142James Kung    private void updatePickers() {
4682e00aa34c051111529290cf23c6ba940c2c0c142James Kung        Iterator<OnDateChangedListener> iterator = mListeners.iterator();
4692e00aa34c051111529290cf23c6ba940c2c0c142James Kung        while (iterator.hasNext()) {
4702e00aa34c051111529290cf23c6ba940c2c0c142James Kung            iterator.next().onDateChanged();
4712e00aa34c051111529290cf23c6ba940c2c0c142James Kung        }
4722e00aa34c051111529290cf23c6ba940c2c0c142James Kung    }
4732e00aa34c051111529290cf23c6ba940c2c0c142James Kung
4743e9818e0267619fecebd55095ab26c53eff92e93James Kung
4753e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4763e9818e0267619fecebd55095ab26c53eff92e93James Kung    public CalendarDay getSelectedDay() {
4773e9818e0267619fecebd55095ab26c53eff92e93James Kung        return new CalendarDay(mCalendar);
4783e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4793e9818e0267619fecebd55095ab26c53eff92e93James Kung
4803e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4813e9818e0267619fecebd55095ab26c53eff92e93James Kung    public int getMinYear() {
4823e9818e0267619fecebd55095ab26c53eff92e93James Kung        return mMinYear;
4833e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4843e9818e0267619fecebd55095ab26c53eff92e93James Kung
4853e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4863e9818e0267619fecebd55095ab26c53eff92e93James Kung    public int getMaxYear() {
4873e9818e0267619fecebd55095ab26c53eff92e93James Kung        return mMaxYear;
4883e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4893e9818e0267619fecebd55095ab26c53eff92e93James Kung
4903e9818e0267619fecebd55095ab26c53eff92e93James Kung    @Override
4913e9818e0267619fecebd55095ab26c53eff92e93James Kung    public int getFirstDayOfWeek() {
4923e9818e0267619fecebd55095ab26c53eff92e93James Kung        return mWeekStart;
4933e9818e0267619fecebd55095ab26c53eff92e93James Kung    }
4942e00aa34c051111529290cf23c6ba940c2c0c142James Kung
4952e00aa34c051111529290cf23c6ba940c2c0c142James Kung    @Override
4962e00aa34c051111529290cf23c6ba940c2c0c142James Kung    public void registerOnDateChangedListener(OnDateChangedListener listener) {
4972e00aa34c051111529290cf23c6ba940c2c0c142James Kung        mListeners.add(listener);
4982e00aa34c051111529290cf23c6ba940c2c0c142James Kung    }
4992e00aa34c051111529290cf23c6ba940c2c0c142James Kung
5002e00aa34c051111529290cf23c6ba940c2c0c142James Kung    @Override
5012e00aa34c051111529290cf23c6ba940c2c0c142James Kung    public void unregisterOnDateChangedListener(OnDateChangedListener listener) {
5022e00aa34c051111529290cf23c6ba940c2c0c142James Kung        mListeners.remove(listener);
5032e00aa34c051111529290cf23c6ba940c2c0c142James Kung    }
5042e00aa34c051111529290cf23c6ba940c2c0c142James Kung
5052e00aa34c051111529290cf23c6ba940c2c0c142James Kung    @Override
5062e00aa34c051111529290cf23c6ba940c2c0c142James Kung    public void tryVibrate() {
5073fc32c45f5efc4ce4b91cbcdd925d9b30f67046ePaul Sliwowski        mHapticFeedbackController.tryVibrate();
5082e00aa34c051111529290cf23c6ba940c2c0c142James Kung    }
5093e9818e0267619fecebd55095ab26c53eff92e93James Kung}
510