The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2007 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.widget; |
| 18 | |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 19 | import android.annotation.Nullable; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 20 | import android.annotation.Widget; |
| 21 | import android.content.Context; |
Svetoslav Ganov | f592696 | 2011-07-12 12:26:20 -0700 | [diff] [blame] | 22 | import android.content.res.Configuration; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 23 | import android.content.res.TypedArray; |
| 24 | import android.os.Parcel; |
| 25 | import android.os.Parcelable; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 26 | import android.util.AttributeSet; |
| 27 | import android.util.SparseArray; |
Svetoslav Ganov | d11e615 | 2012-03-20 12:13:02 -0700 | [diff] [blame] | 28 | import android.view.View; |
Svetoslav Ganov | 8a2a895 | 2011-01-27 17:40:13 -0800 | [diff] [blame] | 29 | import android.view.accessibility.AccessibilityEvent; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 30 | |
Svetoslav Ganov | f592696 | 2011-07-12 12:26:20 -0700 | [diff] [blame] | 31 | import com.android.internal.R; |
| 32 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 33 | import java.util.Calendar; |
Kenny Root | dddda8d | 2010-11-15 14:38:51 -0800 | [diff] [blame] | 34 | import java.util.Locale; |
Svetoslav Ganov | e9730bf | 2010-12-20 21:25:20 -0800 | [diff] [blame] | 35 | import java.util.TimeZone; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 36 | |
| 37 | /** |
Alan Viverette | d25eb9f | 2014-11-24 14:07:24 -0800 | [diff] [blame] | 38 | * Provides a widget for selecting a date. |
| 39 | * <p> |
| 40 | * When the {@link android.R.styleable#DatePicker_datePickerMode} attribute is |
| 41 | * set to {@code spinner}, the date can be selected using year, month, and day |
| 42 | * spinners or a {@link CalendarView}. The set of spinners and the calendar |
| 43 | * view are automatically synchronized. The client can customize whether only |
| 44 | * the spinners, or only the calendar view, or both to be displayed. |
| 45 | * </p> |
| 46 | * <p> |
| 47 | * When the {@link android.R.styleable#DatePicker_datePickerMode} attribute is |
| 48 | * set to {@code calendar}, the month and day can be selected using a |
| 49 | * calendar-style view while the year can be selected separately using a list. |
| 50 | * </p> |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 51 | * <p> |
Scott Main | 4c359b7 | 2012-07-24 15:51:27 -0700 | [diff] [blame] | 52 | * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> |
| 53 | * guide. |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 54 | * </p> |
Svetoslav Ganov | e9730bf | 2010-12-20 21:25:20 -0800 | [diff] [blame] | 55 | * <p> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 56 | * For a dialog using this view, see {@link android.app.DatePickerDialog}. |
Svetoslav Ganov | e9730bf | 2010-12-20 21:25:20 -0800 | [diff] [blame] | 57 | * </p> |
| 58 | * |
| 59 | * @attr ref android.R.styleable#DatePicker_startYear |
| 60 | * @attr ref android.R.styleable#DatePicker_endYear |
| 61 | * @attr ref android.R.styleable#DatePicker_maxDate |
| 62 | * @attr ref android.R.styleable#DatePicker_minDate |
| 63 | * @attr ref android.R.styleable#DatePicker_spinnersShown |
| 64 | * @attr ref android.R.styleable#DatePicker_calendarViewShown |
Alan Viverette | ba9bf41 | 2014-09-03 20:14:21 -0700 | [diff] [blame] | 65 | * @attr ref android.R.styleable#DatePicker_dayOfWeekBackground |
Alan Viverette | 60727e0 | 2014-07-28 16:56:32 -0700 | [diff] [blame] | 66 | * @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance |
Alan Viverette | ba9bf41 | 2014-09-03 20:14:21 -0700 | [diff] [blame] | 67 | * @attr ref android.R.styleable#DatePicker_headerBackground |
Alan Viverette | 60727e0 | 2014-07-28 16:56:32 -0700 | [diff] [blame] | 68 | * @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance |
| 69 | * @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance |
| 70 | * @attr ref android.R.styleable#DatePicker_headerYearTextAppearance |
| 71 | * @attr ref android.R.styleable#DatePicker_yearListItemTextAppearance |
| 72 | * @attr ref android.R.styleable#DatePicker_yearListSelectorColor |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 73 | * @attr ref android.R.styleable#DatePicker_calendarTextColor |
Alan Viverette | d25eb9f | 2014-11-24 14:07:24 -0800 | [diff] [blame] | 74 | * @attr ref android.R.styleable#DatePicker_datePickerMode |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 75 | */ |
| 76 | @Widget |
| 77 | public class DatePicker extends FrameLayout { |
Svetoslav Ganov | e9730bf | 2010-12-20 21:25:20 -0800 | [diff] [blame] | 78 | private static final String LOG_TAG = DatePicker.class.getSimpleName(); |
| 79 | |
Chet Haase | 3053b2f | 2014-08-06 07:51:50 -0700 | [diff] [blame] | 80 | private static final int MODE_SPINNER = 1; |
| 81 | private static final int MODE_CALENDAR = 2; |
| 82 | |
Alan Viverette | 60727e0 | 2014-07-28 16:56:32 -0700 | [diff] [blame] | 83 | private final DatePickerDelegate mDelegate; |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 84 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 85 | /** |
Alan Viverette | 0ef59ac | 2015-03-23 13:13:25 -0700 | [diff] [blame] | 86 | * The callback used to indicate the user changed the date. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 87 | */ |
| 88 | public interface OnDateChangedListener { |
| 89 | |
| 90 | /** |
Svetoslav Ganov | e9730bf | 2010-12-20 21:25:20 -0800 | [diff] [blame] | 91 | * Called upon a date change. |
| 92 | * |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 93 | * @param view The view associated with this listener. |
| 94 | * @param year The year that was set. |
| 95 | * @param monthOfYear The month that was set (0-11) for compatibility |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 96 | * with {@link java.util.Calendar}. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 97 | * @param dayOfMonth The day of the month that was set. |
| 98 | */ |
| 99 | void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth); |
| 100 | } |
| 101 | |
| 102 | public DatePicker(Context context) { |
| 103 | this(context, null); |
| 104 | } |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 105 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 106 | public DatePicker(Context context, AttributeSet attrs) { |
Svetoslav Ganov | 4243dc3 | 2011-01-18 19:39:57 -0800 | [diff] [blame] | 107 | this(context, attrs, R.attr.datePickerStyle); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 108 | } |
| 109 | |
Alan Viverette | 617feb9 | 2013-09-09 18:09:13 -0700 | [diff] [blame] | 110 | public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) { |
| 111 | this(context, attrs, defStyleAttr, 0); |
| 112 | } |
| 113 | |
| 114 | public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { |
| 115 | super(context, attrs, defStyleAttr, defStyleRes); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 116 | |
Alan Viverette | 60727e0 | 2014-07-28 16:56:32 -0700 | [diff] [blame] | 117 | final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, |
| 118 | defStyleAttr, defStyleRes); |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 119 | final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER); |
Alan Viverette | 0a04bb0 | 2014-09-03 20:48:02 -0700 | [diff] [blame] | 120 | final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0); |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 121 | a.recycle(); |
| 122 | |
Chet Haase | 3053b2f | 2014-08-06 07:51:50 -0700 | [diff] [blame] | 123 | switch (mode) { |
| 124 | case MODE_CALENDAR: |
| 125 | mDelegate = createCalendarUIDelegate(context, attrs, defStyleAttr, defStyleRes); |
| 126 | break; |
| 127 | case MODE_SPINNER: |
| 128 | default: |
| 129 | mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes); |
| 130 | break; |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 131 | } |
Alan Viverette | 0a04bb0 | 2014-09-03 20:48:02 -0700 | [diff] [blame] | 132 | |
| 133 | if (firstDayOfWeek != 0) { |
| 134 | setFirstDayOfWeek(firstDayOfWeek); |
| 135 | } |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 136 | } |
| 137 | |
Chet Haase | 3053b2f | 2014-08-06 07:51:50 -0700 | [diff] [blame] | 138 | private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs, |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 139 | int defStyleAttr, int defStyleRes) { |
Chet Haase | 3053b2f | 2014-08-06 07:51:50 -0700 | [diff] [blame] | 140 | return new DatePickerSpinnerDelegate(this, context, attrs, defStyleAttr, defStyleRes); |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 141 | } |
| 142 | |
Chet Haase | 3053b2f | 2014-08-06 07:51:50 -0700 | [diff] [blame] | 143 | private DatePickerDelegate createCalendarUIDelegate(Context context, AttributeSet attrs, |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 144 | int defStyleAttr, int defStyleRes) { |
Chet Haase | 3053b2f | 2014-08-06 07:51:50 -0700 | [diff] [blame] | 145 | return new DatePickerCalendarDelegate(this, context, attrs, defStyleAttr, |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 146 | defStyleRes); |
| 147 | } |
| 148 | |
| 149 | /** |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 150 | * Initialize the state. If the provided values designate an inconsistent |
Svetoslav Ganov | e9730bf | 2010-12-20 21:25:20 -0800 | [diff] [blame] | 151 | * date the values are normalized before updating the spinners. |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 152 | * |
| 153 | * @param year The initial year. |
| 154 | * @param monthOfYear The initial month <strong>starting from zero</strong>. |
| 155 | * @param dayOfMonth The initial day of the month. |
| 156 | * @param onDateChangedListener How user is notified date is changed by |
| 157 | * user, can be null. |
| 158 | */ |
| 159 | public void init(int year, int monthOfYear, int dayOfMonth, |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 160 | OnDateChangedListener onDateChangedListener) { |
| 161 | mDelegate.init(year, monthOfYear, dayOfMonth, onDateChangedListener); |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | /** |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 165 | * Update the current date. |
Svetoslav Ganov | a911d4a | 2010-12-08 16:11:30 -0800 | [diff] [blame] | 166 | * |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 167 | * @param year The year. |
| 168 | * @param month The month which is <strong>starting from zero</strong>. |
| 169 | * @param dayOfMonth The day of the month. |
Svetoslav Ganov | a911d4a | 2010-12-08 16:11:30 -0800 | [diff] [blame] | 170 | */ |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 171 | public void updateDate(int year, int month, int dayOfMonth) { |
| 172 | mDelegate.updateDate(year, month, dayOfMonth); |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | /** |
| 176 | * @return The selected year. |
| 177 | */ |
| 178 | public int getYear() { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 179 | return mDelegate.getYear(); |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | /** |
| 183 | * @return The selected month. |
| 184 | */ |
| 185 | public int getMonth() { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 186 | return mDelegate.getMonth(); |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | /** |
| 190 | * @return The selected day of month. |
| 191 | */ |
| 192 | public int getDayOfMonth() { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 193 | return mDelegate.getDayOfMonth(); |
Svetoslav Ganov | 50f34d1 | 2010-12-03 16:05:40 -0800 | [diff] [blame] | 194 | } |
| 195 | |
| 196 | /** |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 197 | * Gets the minimal date supported by this {@link DatePicker} in |
| 198 | * milliseconds since January 1, 1970 00:00:00 in |
| 199 | * {@link TimeZone#getDefault()} time zone. |
| 200 | * <p> |
| 201 | * Note: The default minimal date is 01/01/1900. |
| 202 | * <p> |
Svetoslav Ganov | a53efe9 | 2011-09-08 18:08:36 -0700 | [diff] [blame] | 203 | * |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 204 | * @return The minimal supported date. |
Svetoslav Ganov | a53efe9 | 2011-09-08 18:08:36 -0700 | [diff] [blame] | 205 | */ |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 206 | public long getMinDate() { |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 207 | return mDelegate.getMinDate().getTimeInMillis(); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 208 | } |
| 209 | |
| 210 | /** |
| 211 | * Sets the minimal date supported by this {@link NumberPicker} in |
| 212 | * milliseconds since January 1, 1970 00:00:00 in |
| 213 | * {@link TimeZone#getDefault()} time zone. |
| 214 | * |
| 215 | * @param minDate The minimal supported date. |
| 216 | */ |
| 217 | public void setMinDate(long minDate) { |
| 218 | mDelegate.setMinDate(minDate); |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * Gets the maximal date supported by this {@link DatePicker} in |
| 223 | * milliseconds since January 1, 1970 00:00:00 in |
| 224 | * {@link TimeZone#getDefault()} time zone. |
| 225 | * <p> |
| 226 | * Note: The default maximal date is 12/31/2100. |
| 227 | * <p> |
| 228 | * |
| 229 | * @return The maximal supported date. |
| 230 | */ |
| 231 | public long getMaxDate() { |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 232 | return mDelegate.getMaxDate().getTimeInMillis(); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 233 | } |
| 234 | |
| 235 | /** |
| 236 | * Sets the maximal date supported by this {@link DatePicker} in |
| 237 | * milliseconds since January 1, 1970 00:00:00 in |
| 238 | * {@link TimeZone#getDefault()} time zone. |
| 239 | * |
| 240 | * @param maxDate The maximal supported date. |
| 241 | */ |
| 242 | public void setMaxDate(long maxDate) { |
| 243 | mDelegate.setMaxDate(maxDate); |
| 244 | } |
| 245 | |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 246 | /** |
| 247 | * Sets the callback that indicates the current date is valid. |
| 248 | * |
| 249 | * @param callback the callback, may be null |
| 250 | * @hide |
| 251 | */ |
| 252 | public void setValidationCallback(@Nullable ValidationCallback callback) { |
| 253 | mDelegate.setValidationCallback(callback); |
| 254 | } |
| 255 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 256 | @Override |
| 257 | public void setEnabled(boolean enabled) { |
| 258 | if (mDelegate.isEnabled() == enabled) { |
| 259 | return; |
Svetoslav Ganov | a53efe9 | 2011-09-08 18:08:36 -0700 | [diff] [blame] | 260 | } |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 261 | super.setEnabled(enabled); |
| 262 | mDelegate.setEnabled(enabled); |
Svetoslav Ganov | a53efe9 | 2011-09-08 18:08:36 -0700 | [diff] [blame] | 263 | } |
| 264 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 265 | @Override |
| 266 | public boolean isEnabled() { |
| 267 | return mDelegate.isEnabled(); |
Svetoslav Ganov | d11e615 | 2012-03-20 12:13:02 -0700 | [diff] [blame] | 268 | } |
| 269 | |
Alan Viverette | a54956a | 2015-01-07 16:05:02 -0800 | [diff] [blame] | 270 | /** @hide */ |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 271 | @Override |
Alan Viverette | a54956a | 2015-01-07 16:05:02 -0800 | [diff] [blame] | 272 | public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 273 | return mDelegate.dispatchPopulateAccessibilityEvent(event); |
| 274 | } |
| 275 | |
Alan Viverette | a54956a | 2015-01-07 16:05:02 -0800 | [diff] [blame] | 276 | /** @hide */ |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 277 | @Override |
Alan Viverette | a54956a | 2015-01-07 16:05:02 -0800 | [diff] [blame] | 278 | public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { |
| 279 | super.onPopulateAccessibilityEventInternal(event); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 280 | mDelegate.onPopulateAccessibilityEvent(event); |
| 281 | } |
| 282 | |
| 283 | @Override |
Dianne Hackborn | a7bb6fb | 2015-02-03 18:13:40 -0800 | [diff] [blame] | 284 | public CharSequence getAccessibilityClassName() { |
| 285 | return DatePicker.class.getName(); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 286 | } |
| 287 | |
| 288 | @Override |
| 289 | protected void onConfigurationChanged(Configuration newConfig) { |
| 290 | super.onConfigurationChanged(newConfig); |
| 291 | mDelegate.onConfigurationChanged(newConfig); |
| 292 | } |
| 293 | |
| 294 | /** |
Alan Viverette | 0a04bb0 | 2014-09-03 20:48:02 -0700 | [diff] [blame] | 295 | * Sets the first day of week. |
| 296 | * |
| 297 | * @param firstDayOfWeek The first day of the week conforming to the |
| 298 | * {@link CalendarView} APIs. |
| 299 | * @see Calendar#SUNDAY |
| 300 | * @see Calendar#MONDAY |
| 301 | * @see Calendar#TUESDAY |
| 302 | * @see Calendar#WEDNESDAY |
| 303 | * @see Calendar#THURSDAY |
| 304 | * @see Calendar#FRIDAY |
| 305 | * @see Calendar#SATURDAY |
| 306 | * |
| 307 | * @attr ref android.R.styleable#DatePicker_firstDayOfWeek |
| 308 | */ |
| 309 | public void setFirstDayOfWeek(int firstDayOfWeek) { |
| 310 | if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) { |
| 311 | throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7"); |
| 312 | } |
| 313 | mDelegate.setFirstDayOfWeek(firstDayOfWeek); |
| 314 | } |
| 315 | |
| 316 | /** |
| 317 | * Gets the first day of week. |
| 318 | * |
| 319 | * @return The first day of the week conforming to the {@link CalendarView} |
| 320 | * APIs. |
| 321 | * @see Calendar#SUNDAY |
| 322 | * @see Calendar#MONDAY |
| 323 | * @see Calendar#TUESDAY |
| 324 | * @see Calendar#WEDNESDAY |
| 325 | * @see Calendar#THURSDAY |
| 326 | * @see Calendar#FRIDAY |
| 327 | * @see Calendar#SATURDAY |
| 328 | * |
| 329 | * @attr ref android.R.styleable#DatePicker_firstDayOfWeek |
| 330 | */ |
| 331 | public int getFirstDayOfWeek() { |
| 332 | return mDelegate.getFirstDayOfWeek(); |
| 333 | } |
| 334 | |
| 335 | /** |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 336 | * Returns whether the {@link CalendarView} is shown. |
| 337 | * <p> |
| 338 | * <strong>Note:</strong> This method returns {@code false} when the |
| 339 | * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set |
| 340 | * to {@code calendar}. |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 341 | * |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 342 | * @return {@code true} if the calendar view is shown |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 343 | * @see #getCalendarView() |
| 344 | */ |
| 345 | public boolean getCalendarViewShown() { |
| 346 | return mDelegate.getCalendarViewShown(); |
| 347 | } |
| 348 | |
| 349 | /** |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 350 | * Returns the {@link CalendarView} used by this picker. |
Alan Viverette | d25eb9f | 2014-11-24 14:07:24 -0800 | [diff] [blame] | 351 | * <p> |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 352 | * <strong>Note:</strong> This method returns {@code null} when the |
Alan Viverette | d25eb9f | 2014-11-24 14:07:24 -0800 | [diff] [blame] | 353 | * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set |
| 354 | * to {@code calendar}. |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 355 | * |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 356 | * @return the calendar view |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 357 | * @see #getCalendarViewShown() |
| 358 | */ |
Alan Viverette | 0a04bb0 | 2014-09-03 20:48:02 -0700 | [diff] [blame] | 359 | public CalendarView getCalendarView() { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 360 | return mDelegate.getCalendarView(); |
| 361 | } |
| 362 | |
| 363 | /** |
| 364 | * Sets whether the {@link CalendarView} is shown. |
Alan Viverette | d25eb9f | 2014-11-24 14:07:24 -0800 | [diff] [blame] | 365 | * <p> |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 366 | * <strong>Note:</strong> Calling this method has no effect when the |
Alan Viverette | d25eb9f | 2014-11-24 14:07:24 -0800 | [diff] [blame] | 367 | * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set |
| 368 | * to {@code calendar}. |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 369 | * |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 370 | * @param shown {@code true} to show the calendar view, {@code false} to |
| 371 | * hide it |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 372 | */ |
| 373 | public void setCalendarViewShown(boolean shown) { |
| 374 | mDelegate.setCalendarViewShown(shown); |
| 375 | } |
| 376 | |
| 377 | /** |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 378 | * Returns whether the spinners are shown. |
| 379 | * <p> |
Alan Viverette | 835d798 | 2015-03-23 14:54:14 -0700 | [diff] [blame] | 380 | * <strong>Note:</strong> his method returns {@code false} when the |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 381 | * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set |
| 382 | * to {@code calendar}. |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 383 | * |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 384 | * @return {@code true} if the spinners are shown |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 385 | */ |
| 386 | public boolean getSpinnersShown() { |
| 387 | return mDelegate.getSpinnersShown(); |
| 388 | } |
| 389 | |
| 390 | /** |
| 391 | * Sets whether the spinners are shown. |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 392 | * <p> |
| 393 | * Calling this method has no effect when the |
| 394 | * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set |
| 395 | * to {@code calendar}. |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 396 | * |
Alan Viverette | 452fe34 | 2015-03-23 14:26:09 -0700 | [diff] [blame] | 397 | * @param shown {@code true} to show the spinners, {@code false} to hide |
| 398 | * them |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 399 | */ |
| 400 | public void setSpinnersShown(boolean shown) { |
| 401 | mDelegate.setSpinnersShown(shown); |
| 402 | } |
| 403 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 404 | @Override |
| 405 | protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { |
Alan Viverette | d015e34 | 2014-09-15 19:27:55 -0700 | [diff] [blame] | 406 | dispatchThawSelfOnly(container); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 407 | } |
| 408 | |
| 409 | @Override |
| 410 | protected Parcelable onSaveInstanceState() { |
| 411 | Parcelable superState = super.onSaveInstanceState(); |
| 412 | return mDelegate.onSaveInstanceState(superState); |
| 413 | } |
| 414 | |
| 415 | @Override |
| 416 | protected void onRestoreInstanceState(Parcelable state) { |
Craig Mautner | a67d909 | 2014-09-16 15:38:47 -0700 | [diff] [blame] | 417 | BaseSavedState ss = (BaseSavedState) state; |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 418 | super.onRestoreInstanceState(ss.getSuperState()); |
| 419 | mDelegate.onRestoreInstanceState(ss); |
| 420 | } |
| 421 | |
| 422 | /** |
| 423 | * A delegate interface that defined the public API of the DatePicker. Allows different |
| 424 | * DatePicker implementations. This would need to be implemented by the DatePicker delegates |
| 425 | * for the real behavior. |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 426 | * |
| 427 | * @hide |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 428 | */ |
| 429 | interface DatePickerDelegate { |
| 430 | void init(int year, int monthOfYear, int dayOfMonth, |
| 431 | OnDateChangedListener onDateChangedListener); |
| 432 | |
| 433 | void updateDate(int year, int month, int dayOfMonth); |
| 434 | |
| 435 | int getYear(); |
| 436 | int getMonth(); |
| 437 | int getDayOfMonth(); |
| 438 | |
Alan Viverette | 0a04bb0 | 2014-09-03 20:48:02 -0700 | [diff] [blame] | 439 | void setFirstDayOfWeek(int firstDayOfWeek); |
| 440 | int getFirstDayOfWeek(); |
| 441 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 442 | void setMinDate(long minDate); |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 443 | Calendar getMinDate(); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 444 | |
| 445 | void setMaxDate(long maxDate); |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 446 | Calendar getMaxDate(); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 447 | |
| 448 | void setEnabled(boolean enabled); |
| 449 | boolean isEnabled(); |
| 450 | |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 451 | CalendarView getCalendarView(); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 452 | |
| 453 | void setCalendarViewShown(boolean shown); |
| 454 | boolean getCalendarViewShown(); |
| 455 | |
| 456 | void setSpinnersShown(boolean shown); |
| 457 | boolean getSpinnersShown(); |
| 458 | |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 459 | void setValidationCallback(ValidationCallback callback); |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 460 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 461 | void onConfigurationChanged(Configuration newConfig); |
| 462 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 463 | Parcelable onSaveInstanceState(Parcelable superState); |
| 464 | void onRestoreInstanceState(Parcelable state); |
| 465 | |
| 466 | boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event); |
| 467 | void onPopulateAccessibilityEvent(AccessibilityEvent event); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 468 | } |
| 469 | |
| 470 | /** |
| 471 | * An abstract class which can be used as a start for DatePicker implementations |
| 472 | */ |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 473 | abstract static class AbstractDatePickerDelegate implements DatePickerDelegate { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 474 | // The delegator |
| 475 | protected DatePicker mDelegator; |
| 476 | |
| 477 | // The context |
| 478 | protected Context mContext; |
| 479 | |
| 480 | // The current locale |
| 481 | protected Locale mCurrentLocale; |
| 482 | |
| 483 | // Callbacks |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 484 | protected OnDateChangedListener mOnDateChangedListener; |
| 485 | protected ValidationCallback mValidationCallback; |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 486 | |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 487 | public AbstractDatePickerDelegate(DatePicker delegator, Context context) { |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 488 | mDelegator = delegator; |
| 489 | mContext = context; |
| 490 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 491 | setCurrentLocale(Locale.getDefault()); |
| 492 | } |
| 493 | |
| 494 | protected void setCurrentLocale(Locale locale) { |
Alan Viverette | 0ef59ac | 2015-03-23 13:13:25 -0700 | [diff] [blame] | 495 | if (!locale.equals(mCurrentLocale)) { |
| 496 | mCurrentLocale = locale; |
| 497 | onLocaleChanged(locale); |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 498 | } |
Svetoslav Ganov | d11e615 | 2012-03-20 12:13:02 -0700 | [diff] [blame] | 499 | } |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 500 | |
| 501 | @Override |
| 502 | public void setValidationCallback(ValidationCallback callback) { |
| 503 | mValidationCallback = callback; |
| 504 | } |
| 505 | |
| 506 | protected void onValidationChanged(boolean valid) { |
| 507 | if (mValidationCallback != null) { |
| 508 | mValidationCallback.onValidationChanged(valid); |
| 509 | } |
| 510 | } |
Alan Viverette | 0ef59ac | 2015-03-23 13:13:25 -0700 | [diff] [blame] | 511 | |
| 512 | protected void onLocaleChanged(Locale locale) { |
| 513 | // Stub. |
| 514 | } |
Alan Viverette | 6b3f85f | 2016-03-01 16:48:04 -0500 | [diff] [blame] | 515 | |
| 516 | /** |
| 517 | * Class for managing state storing/restoring. |
| 518 | */ |
| 519 | static class SavedState extends View.BaseSavedState { |
| 520 | private final int mSelectedYear; |
| 521 | private final int mSelectedMonth; |
| 522 | private final int mSelectedDay; |
| 523 | private final long mMinDate; |
| 524 | private final long mMaxDate; |
| 525 | private final int mCurrentView; |
| 526 | private final int mListPosition; |
| 527 | private final int mListPositionOffset; |
| 528 | |
| 529 | public SavedState(Parcelable superState, int year, int month, int day, long minDate, |
| 530 | long maxDate) { |
| 531 | this(superState, year, month, day, minDate, maxDate, 0, 0, 0); |
| 532 | } |
| 533 | |
| 534 | /** |
| 535 | * Constructor called from {@link DatePicker#onSaveInstanceState()} |
| 536 | */ |
| 537 | public SavedState(Parcelable superState, int year, int month, int day, long minDate, |
| 538 | long maxDate, int currentView, int listPosition, int listPositionOffset) { |
| 539 | super(superState); |
| 540 | mSelectedYear = year; |
| 541 | mSelectedMonth = month; |
| 542 | mSelectedDay = day; |
| 543 | mMinDate = minDate; |
| 544 | mMaxDate = maxDate; |
| 545 | mCurrentView = currentView; |
| 546 | mListPosition = listPosition; |
| 547 | mListPositionOffset = listPositionOffset; |
| 548 | } |
| 549 | |
| 550 | /** |
| 551 | * Constructor called from {@link #CREATOR} |
| 552 | */ |
| 553 | private SavedState(Parcel in) { |
| 554 | super(in); |
| 555 | mSelectedYear = in.readInt(); |
| 556 | mSelectedMonth = in.readInt(); |
| 557 | mSelectedDay = in.readInt(); |
| 558 | mMinDate = in.readLong(); |
| 559 | mMaxDate = in.readLong(); |
| 560 | mCurrentView = in.readInt(); |
| 561 | mListPosition = in.readInt(); |
| 562 | mListPositionOffset = in.readInt(); |
| 563 | } |
| 564 | |
| 565 | @Override |
| 566 | public void writeToParcel(Parcel dest, int flags) { |
| 567 | super.writeToParcel(dest, flags); |
| 568 | dest.writeInt(mSelectedYear); |
| 569 | dest.writeInt(mSelectedMonth); |
| 570 | dest.writeInt(mSelectedDay); |
| 571 | dest.writeLong(mMinDate); |
| 572 | dest.writeLong(mMaxDate); |
| 573 | dest.writeInt(mCurrentView); |
| 574 | dest.writeInt(mListPosition); |
| 575 | dest.writeInt(mListPositionOffset); |
| 576 | } |
| 577 | |
| 578 | public int getSelectedDay() { |
| 579 | return mSelectedDay; |
| 580 | } |
| 581 | |
| 582 | public int getSelectedMonth() { |
| 583 | return mSelectedMonth; |
| 584 | } |
| 585 | |
| 586 | public int getSelectedYear() { |
| 587 | return mSelectedYear; |
| 588 | } |
| 589 | |
| 590 | public long getMinDate() { |
| 591 | return mMinDate; |
| 592 | } |
| 593 | |
| 594 | public long getMaxDate() { |
| 595 | return mMaxDate; |
| 596 | } |
| 597 | |
| 598 | public int getCurrentView() { |
| 599 | return mCurrentView; |
| 600 | } |
| 601 | |
| 602 | public int getListPosition() { |
| 603 | return mListPosition; |
| 604 | } |
| 605 | |
| 606 | public int getListPositionOffset() { |
| 607 | return mListPositionOffset; |
| 608 | } |
| 609 | |
| 610 | @SuppressWarnings("all") |
| 611 | // suppress unused and hiding |
| 612 | public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() { |
| 613 | |
| 614 | public SavedState createFromParcel(Parcel in) { |
| 615 | return new SavedState(in); |
| 616 | } |
| 617 | |
| 618 | public SavedState[] newArray(int size) { |
| 619 | return new SavedState[size]; |
| 620 | } |
| 621 | }; |
| 622 | } |
Svetoslav Ganov | a53efe9 | 2011-09-08 18:08:36 -0700 | [diff] [blame] | 623 | } |
| 624 | |
Fabrice Di Meglio | 039a784 | 2013-08-28 17:41:26 -0700 | [diff] [blame] | 625 | /** |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 626 | * A callback interface for updating input validity when the date picker |
| 627 | * when included into a dialog. |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 628 | * |
| 629 | * @hide |
| 630 | */ |
Alan Viverette | 6b3f85f | 2016-03-01 16:48:04 -0500 | [diff] [blame] | 631 | public interface ValidationCallback { |
Alan Viverette | 518ff0d | 2014-08-15 14:20:35 -0700 | [diff] [blame] | 632 | void onValidationChanged(boolean valid); |
Fabrice Di Meglio | bd9152f | 2013-10-01 11:21:31 -0700 | [diff] [blame] | 633 | } |
Svetoslav Ganov | 3fec3fe | 2011-09-01 14:48:37 -0700 | [diff] [blame] | 634 | } |