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 19 import android.annotation.IntDef; 20 import android.annotation.Nullable; 21 import android.annotation.TestApi; 22 import android.annotation.Widget; 23 import android.content.Context; 24 import android.content.res.Configuration; 25 import android.content.res.TypedArray; 26 import android.icu.util.Calendar; 27 import android.icu.util.TimeZone; 28 import android.os.Parcel; 29 import android.os.Parcelable; 30 import android.text.format.DateUtils; 31 import android.util.AttributeSet; 32 import android.util.Log; 33 import android.util.SparseArray; 34 import android.view.View; 35 import android.view.ViewStructure; 36 import android.view.accessibility.AccessibilityEvent; 37 import android.view.autofill.AutofillManager; 38 import android.view.autofill.AutofillValue; 39 40 import com.android.internal.R; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.Locale; 45 46 /** 47 * Provides a widget for selecting a date. 48 * <p> 49 * When the {@link android.R.styleable#DatePicker_datePickerMode} attribute is 50 * set to {@code spinner}, the date can be selected using year, month, and day 51 * spinners or a {@link CalendarView}. The set of spinners and the calendar 52 * view are automatically synchronized. The client can customize whether only 53 * the spinners, or only the calendar view, or both to be displayed. 54 * </p> 55 * <p> 56 * When the {@link android.R.styleable#DatePicker_datePickerMode} attribute is 57 * set to {@code calendar}, the month and day can be selected using a 58 * calendar-style view while the year can be selected separately using a list. 59 * </p> 60 * <p> 61 * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> 62 * guide. 63 * </p> 64 * <p> 65 * For a dialog using this view, see {@link android.app.DatePickerDialog}. 66 * </p> 67 * 68 * @attr ref android.R.styleable#DatePicker_startYear 69 * @attr ref android.R.styleable#DatePicker_endYear 70 * @attr ref android.R.styleable#DatePicker_maxDate 71 * @attr ref android.R.styleable#DatePicker_minDate 72 * @attr ref android.R.styleable#DatePicker_spinnersShown 73 * @attr ref android.R.styleable#DatePicker_calendarViewShown 74 * @attr ref android.R.styleable#DatePicker_dayOfWeekBackground 75 * @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance 76 * @attr ref android.R.styleable#DatePicker_headerBackground 77 * @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance 78 * @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance 79 * @attr ref android.R.styleable#DatePicker_headerYearTextAppearance 80 * @attr ref android.R.styleable#DatePicker_yearListItemTextAppearance 81 * @attr ref android.R.styleable#DatePicker_yearListSelectorColor 82 * @attr ref android.R.styleable#DatePicker_calendarTextColor 83 * @attr ref android.R.styleable#DatePicker_datePickerMode 84 */ 85 @Widget 86 public class DatePicker extends FrameLayout { 87 private static final String LOG_TAG = DatePicker.class.getSimpleName(); 88 89 /** 90 * Presentation mode for the Holo-style date picker that uses a set of 91 * {@link android.widget.NumberPicker}s. 92 * 93 * @see #getMode() 94 * @hide Visible for testing only. 95 */ 96 @TestApi 97 public static final int MODE_SPINNER = 1; 98 99 /** 100 * Presentation mode for the Material-style date picker that uses a 101 * calendar. 102 * 103 * @see #getMode() 104 * @hide Visible for testing only. 105 */ 106 @TestApi 107 public static final int MODE_CALENDAR = 2; 108 109 /** @hide */ 110 @IntDef(prefix = { "MODE_" }, value = { 111 MODE_SPINNER, 112 MODE_CALENDAR 113 }) 114 @Retention(RetentionPolicy.SOURCE) 115 public @interface DatePickerMode {} 116 117 private final DatePickerDelegate mDelegate; 118 119 @DatePickerMode 120 private final int mMode; 121 122 /** 123 * The callback used to indicate the user changed the date. 124 */ 125 public interface OnDateChangedListener { 126 127 /** 128 * Called upon a date change. 129 * 130 * @param view The view associated with this listener. 131 * @param year The year that was set. 132 * @param monthOfYear The month that was set (0-11) for compatibility 133 * with {@link java.util.Calendar}. 134 * @param dayOfMonth The day of the month that was set. 135 */ 136 void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth); 137 } 138 139 public DatePicker(Context context) { 140 this(context, null); 141 } 142 143 public DatePicker(Context context, AttributeSet attrs) { 144 this(context, attrs, R.attr.datePickerStyle); 145 } 146 147 public DatePicker(Context context, AttributeSet attrs, int defStyleAttr) { 148 this(context, attrs, defStyleAttr, 0); 149 } 150 151 public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 152 super(context, attrs, defStyleAttr, defStyleRes); 153 154 // DatePicker is important by default, unless app developer overrode attribute. 155 if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) { 156 setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES); 157 } 158 159 final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, 160 defStyleAttr, defStyleRes); 161 final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false); 162 final int requestedMode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER); 163 final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0); 164 a.recycle(); 165 166 if (requestedMode == MODE_CALENDAR && isDialogMode) { 167 // You want MODE_CALENDAR? YOU CAN'T HANDLE MODE_CALENDAR! Well, 168 // maybe you can depending on your screen size. Let's check... 169 mMode = context.getResources().getInteger(R.integer.date_picker_mode); 170 } else { 171 mMode = requestedMode; 172 } 173 174 switch (mMode) { 175 case MODE_CALENDAR: 176 mDelegate = createCalendarUIDelegate(context, attrs, defStyleAttr, defStyleRes); 177 break; 178 case MODE_SPINNER: 179 default: 180 mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes); 181 break; 182 } 183 184 if (firstDayOfWeek != 0) { 185 setFirstDayOfWeek(firstDayOfWeek); 186 } 187 188 mDelegate.setAutoFillChangeListener((v, y, m, d) -> { 189 final AutofillManager afm = context.getSystemService(AutofillManager.class); 190 if (afm != null) { 191 afm.notifyValueChanged(this); 192 } 193 }); 194 } 195 196 private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs, 197 int defStyleAttr, int defStyleRes) { 198 return new DatePickerSpinnerDelegate(this, context, attrs, defStyleAttr, defStyleRes); 199 } 200 201 private DatePickerDelegate createCalendarUIDelegate(Context context, AttributeSet attrs, 202 int defStyleAttr, int defStyleRes) { 203 return new DatePickerCalendarDelegate(this, context, attrs, defStyleAttr, 204 defStyleRes); 205 } 206 207 /** 208 * @return the picker's presentation mode, one of {@link #MODE_CALENDAR} or 209 * {@link #MODE_SPINNER} 210 * @attr ref android.R.styleable#DatePicker_datePickerMode 211 * @hide Visible for testing only. 212 */ 213 @DatePickerMode 214 @TestApi 215 public int getMode() { 216 return mMode; 217 } 218 219 /** 220 * Initialize the state. If the provided values designate an inconsistent 221 * date the values are normalized before updating the spinners. 222 * 223 * @param year The initial year. 224 * @param monthOfYear The initial month <strong>starting from zero</strong>. 225 * @param dayOfMonth The initial day of the month. 226 * @param onDateChangedListener How user is notified date is changed by 227 * user, can be null. 228 */ 229 public void init(int year, int monthOfYear, int dayOfMonth, 230 OnDateChangedListener onDateChangedListener) { 231 mDelegate.init(year, monthOfYear, dayOfMonth, onDateChangedListener); 232 } 233 234 /** 235 * Set the callback that indicates the date has been adjusted by the user. 236 * 237 * @param onDateChangedListener How user is notified date is changed by 238 * user, can be null. 239 */ 240 public void setOnDateChangedListener(OnDateChangedListener onDateChangedListener) { 241 mDelegate.setOnDateChangedListener(onDateChangedListener); 242 } 243 244 /** 245 * Update the current date. 246 * 247 * @param year The year. 248 * @param month The month which is <strong>starting from zero</strong>. 249 * @param dayOfMonth The day of the month. 250 */ 251 public void updateDate(int year, int month, int dayOfMonth) { 252 mDelegate.updateDate(year, month, dayOfMonth); 253 } 254 255 /** 256 * @return The selected year. 257 */ 258 public int getYear() { 259 return mDelegate.getYear(); 260 } 261 262 /** 263 * @return The selected month. 264 */ 265 public int getMonth() { 266 return mDelegate.getMonth(); 267 } 268 269 /** 270 * @return The selected day of month. 271 */ 272 public int getDayOfMonth() { 273 return mDelegate.getDayOfMonth(); 274 } 275 276 /** 277 * Gets the minimal date supported by this {@link DatePicker} in 278 * milliseconds since January 1, 1970 00:00:00 in 279 * {@link TimeZone#getDefault()} time zone. 280 * <p> 281 * Note: The default minimal date is 01/01/1900. 282 * <p> 283 * 284 * @return The minimal supported date. 285 */ 286 public long getMinDate() { 287 return mDelegate.getMinDate().getTimeInMillis(); 288 } 289 290 /** 291 * Sets the minimal date supported by this {@link NumberPicker} in 292 * milliseconds since January 1, 1970 00:00:00 in 293 * {@link TimeZone#getDefault()} time zone. 294 * 295 * @param minDate The minimal supported date. 296 */ 297 public void setMinDate(long minDate) { 298 mDelegate.setMinDate(minDate); 299 } 300 301 /** 302 * Gets the maximal date supported by this {@link DatePicker} in 303 * milliseconds since January 1, 1970 00:00:00 in 304 * {@link TimeZone#getDefault()} time zone. 305 * <p> 306 * Note: The default maximal date is 12/31/2100. 307 * <p> 308 * 309 * @return The maximal supported date. 310 */ 311 public long getMaxDate() { 312 return mDelegate.getMaxDate().getTimeInMillis(); 313 } 314 315 /** 316 * Sets the maximal date supported by this {@link DatePicker} in 317 * milliseconds since January 1, 1970 00:00:00 in 318 * {@link TimeZone#getDefault()} time zone. 319 * 320 * @param maxDate The maximal supported date. 321 */ 322 public void setMaxDate(long maxDate) { 323 mDelegate.setMaxDate(maxDate); 324 } 325 326 /** 327 * Sets the callback that indicates the current date is valid. 328 * 329 * @param callback the callback, may be null 330 * @hide 331 */ 332 public void setValidationCallback(@Nullable ValidationCallback callback) { 333 mDelegate.setValidationCallback(callback); 334 } 335 336 @Override 337 public void setEnabled(boolean enabled) { 338 if (mDelegate.isEnabled() == enabled) { 339 return; 340 } 341 super.setEnabled(enabled); 342 mDelegate.setEnabled(enabled); 343 } 344 345 @Override 346 public boolean isEnabled() { 347 return mDelegate.isEnabled(); 348 } 349 350 /** @hide */ 351 @Override 352 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 353 return mDelegate.dispatchPopulateAccessibilityEvent(event); 354 } 355 356 /** @hide */ 357 @Override 358 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 359 super.onPopulateAccessibilityEventInternal(event); 360 mDelegate.onPopulateAccessibilityEvent(event); 361 } 362 363 @Override 364 public CharSequence getAccessibilityClassName() { 365 return DatePicker.class.getName(); 366 } 367 368 @Override 369 protected void onConfigurationChanged(Configuration newConfig) { 370 super.onConfigurationChanged(newConfig); 371 mDelegate.onConfigurationChanged(newConfig); 372 } 373 374 /** 375 * Sets the first day of week. 376 * 377 * @param firstDayOfWeek The first day of the week conforming to the 378 * {@link CalendarView} APIs. 379 * @see Calendar#SUNDAY 380 * @see Calendar#MONDAY 381 * @see Calendar#TUESDAY 382 * @see Calendar#WEDNESDAY 383 * @see Calendar#THURSDAY 384 * @see Calendar#FRIDAY 385 * @see Calendar#SATURDAY 386 * 387 * @attr ref android.R.styleable#DatePicker_firstDayOfWeek 388 */ 389 public void setFirstDayOfWeek(int firstDayOfWeek) { 390 if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) { 391 throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7"); 392 } 393 mDelegate.setFirstDayOfWeek(firstDayOfWeek); 394 } 395 396 /** 397 * Gets the first day of week. 398 * 399 * @return The first day of the week conforming to the {@link CalendarView} 400 * APIs. 401 * @see Calendar#SUNDAY 402 * @see Calendar#MONDAY 403 * @see Calendar#TUESDAY 404 * @see Calendar#WEDNESDAY 405 * @see Calendar#THURSDAY 406 * @see Calendar#FRIDAY 407 * @see Calendar#SATURDAY 408 * 409 * @attr ref android.R.styleable#DatePicker_firstDayOfWeek 410 */ 411 public int getFirstDayOfWeek() { 412 return mDelegate.getFirstDayOfWeek(); 413 } 414 415 /** 416 * Returns whether the {@link CalendarView} is shown. 417 * <p> 418 * <strong>Note:</strong> This method returns {@code false} when the 419 * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set 420 * to {@code calendar}. 421 * 422 * @return {@code true} if the calendar view is shown 423 * @see #getCalendarView() 424 * @deprecated Not supported by Material-style {@code calendar} mode 425 */ 426 @Deprecated 427 public boolean getCalendarViewShown() { 428 return mDelegate.getCalendarViewShown(); 429 } 430 431 /** 432 * Returns the {@link CalendarView} used by this picker. 433 * <p> 434 * <strong>Note:</strong> This method throws an 435 * {@link UnsupportedOperationException} when the 436 * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set 437 * to {@code calendar}. 438 * 439 * @return the calendar view 440 * @see #getCalendarViewShown() 441 * @deprecated Not supported by Material-style {@code calendar} mode 442 * @throws UnsupportedOperationException if called when the picker is 443 * displayed in {@code calendar} mode 444 */ 445 @Deprecated 446 public CalendarView getCalendarView() { 447 return mDelegate.getCalendarView(); 448 } 449 450 /** 451 * Sets whether the {@link CalendarView} is shown. 452 * <p> 453 * <strong>Note:</strong> Calling this method has no effect when the 454 * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set 455 * to {@code calendar}. 456 * 457 * @param shown {@code true} to show the calendar view, {@code false} to 458 * hide it 459 * @deprecated Not supported by Material-style {@code calendar} mode 460 */ 461 @Deprecated 462 public void setCalendarViewShown(boolean shown) { 463 mDelegate.setCalendarViewShown(shown); 464 } 465 466 /** 467 * Returns whether the spinners are shown. 468 * <p> 469 * <strong>Note:</strong> his method returns {@code false} when the 470 * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set 471 * to {@code calendar}. 472 * 473 * @return {@code true} if the spinners are shown 474 * @deprecated Not supported by Material-style {@code calendar} mode 475 */ 476 @Deprecated 477 public boolean getSpinnersShown() { 478 return mDelegate.getSpinnersShown(); 479 } 480 481 /** 482 * Sets whether the spinners are shown. 483 * <p> 484 * Calling this method has no effect when the 485 * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set 486 * to {@code calendar}. 487 * 488 * @param shown {@code true} to show the spinners, {@code false} to hide 489 * them 490 * @deprecated Not supported by Material-style {@code calendar} mode 491 */ 492 @Deprecated 493 public void setSpinnersShown(boolean shown) { 494 mDelegate.setSpinnersShown(shown); 495 } 496 497 @Override 498 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 499 dispatchThawSelfOnly(container); 500 } 501 502 @Override 503 protected Parcelable onSaveInstanceState() { 504 Parcelable superState = super.onSaveInstanceState(); 505 return mDelegate.onSaveInstanceState(superState); 506 } 507 508 @Override 509 protected void onRestoreInstanceState(Parcelable state) { 510 BaseSavedState ss = (BaseSavedState) state; 511 super.onRestoreInstanceState(ss.getSuperState()); 512 mDelegate.onRestoreInstanceState(ss); 513 } 514 515 /** 516 * A delegate interface that defined the public API of the DatePicker. Allows different 517 * DatePicker implementations. This would need to be implemented by the DatePicker delegates 518 * for the real behavior. 519 * 520 * @hide 521 */ 522 interface DatePickerDelegate { 523 void init(int year, int monthOfYear, int dayOfMonth, 524 OnDateChangedListener onDateChangedListener); 525 526 void setOnDateChangedListener(OnDateChangedListener onDateChangedListener); 527 void setAutoFillChangeListener(OnDateChangedListener onDateChangedListener); 528 529 void updateDate(int year, int month, int dayOfMonth); 530 531 int getYear(); 532 int getMonth(); 533 int getDayOfMonth(); 534 535 void autofill(AutofillValue value); 536 AutofillValue getAutofillValue(); 537 538 void setFirstDayOfWeek(int firstDayOfWeek); 539 int getFirstDayOfWeek(); 540 541 void setMinDate(long minDate); 542 Calendar getMinDate(); 543 544 void setMaxDate(long maxDate); 545 Calendar getMaxDate(); 546 547 void setEnabled(boolean enabled); 548 boolean isEnabled(); 549 550 CalendarView getCalendarView(); 551 552 void setCalendarViewShown(boolean shown); 553 boolean getCalendarViewShown(); 554 555 void setSpinnersShown(boolean shown); 556 boolean getSpinnersShown(); 557 558 void setValidationCallback(ValidationCallback callback); 559 560 void onConfigurationChanged(Configuration newConfig); 561 562 Parcelable onSaveInstanceState(Parcelable superState); 563 void onRestoreInstanceState(Parcelable state); 564 565 boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event); 566 void onPopulateAccessibilityEvent(AccessibilityEvent event); 567 } 568 569 /** 570 * An abstract class which can be used as a start for DatePicker implementations 571 */ 572 abstract static class AbstractDatePickerDelegate implements DatePickerDelegate { 573 // The delegator 574 protected DatePicker mDelegator; 575 576 // The context 577 protected Context mContext; 578 579 // NOTE: when subclasses change this variable, they must call resetAutofilledValue(). 580 protected Calendar mCurrentDate; 581 582 // The current locale 583 protected Locale mCurrentLocale; 584 585 // Callbacks 586 protected OnDateChangedListener mOnDateChangedListener; 587 protected OnDateChangedListener mAutoFillChangeListener; 588 protected ValidationCallback mValidationCallback; 589 590 // The value that was passed to autofill() - it must be stored because it getAutofillValue() 591 // must return the exact same value that was autofilled, otherwise the widget will not be 592 // properly highlighted after autofill(). 593 private long mAutofilledValue; 594 595 public AbstractDatePickerDelegate(DatePicker delegator, Context context) { 596 mDelegator = delegator; 597 mContext = context; 598 599 setCurrentLocale(Locale.getDefault()); 600 } 601 602 protected void setCurrentLocale(Locale locale) { 603 if (!locale.equals(mCurrentLocale)) { 604 mCurrentLocale = locale; 605 onLocaleChanged(locale); 606 } 607 } 608 609 @Override 610 public void setOnDateChangedListener(OnDateChangedListener callback) { 611 mOnDateChangedListener = callback; 612 } 613 614 @Override 615 public void setAutoFillChangeListener(OnDateChangedListener callback) { 616 mAutoFillChangeListener = callback; 617 } 618 619 @Override 620 public void setValidationCallback(ValidationCallback callback) { 621 mValidationCallback = callback; 622 } 623 624 @Override 625 public final void autofill(AutofillValue value) { 626 if (value == null || !value.isDate()) { 627 Log.w(LOG_TAG, value + " could not be autofilled into " + this); 628 return; 629 } 630 631 final long time = value.getDateValue(); 632 633 final Calendar cal = Calendar.getInstance(mCurrentLocale); 634 cal.setTimeInMillis(time); 635 updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 636 cal.get(Calendar.DAY_OF_MONTH)); 637 638 // Must set mAutofilledValue *after* calling subclass method to make sure the value 639 // returned by getAutofillValue() matches it. 640 mAutofilledValue = time; 641 } 642 643 @Override 644 public final AutofillValue getAutofillValue() { 645 final long time = mAutofilledValue != 0 646 ? mAutofilledValue 647 : mCurrentDate.getTimeInMillis(); 648 return AutofillValue.forDate(time); 649 } 650 651 /** 652 * This method must be called every time the value of the year, month, and/or day is 653 * changed by a subclass method. 654 */ 655 protected void resetAutofilledValue() { 656 mAutofilledValue = 0; 657 } 658 659 protected void onValidationChanged(boolean valid) { 660 if (mValidationCallback != null) { 661 mValidationCallback.onValidationChanged(valid); 662 } 663 } 664 665 protected void onLocaleChanged(Locale locale) { 666 // Stub. 667 } 668 669 @Override 670 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 671 event.getText().add(getFormattedCurrentDate()); 672 } 673 674 protected String getFormattedCurrentDate() { 675 return DateUtils.formatDateTime(mContext, mCurrentDate.getTimeInMillis(), 676 DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR 677 | DateUtils.FORMAT_SHOW_WEEKDAY); 678 } 679 680 /** 681 * Class for managing state storing/restoring. 682 */ 683 static class SavedState extends View.BaseSavedState { 684 private final int mSelectedYear; 685 private final int mSelectedMonth; 686 private final int mSelectedDay; 687 private final long mMinDate; 688 private final long mMaxDate; 689 private final int mCurrentView; 690 private final int mListPosition; 691 private final int mListPositionOffset; 692 693 public SavedState(Parcelable superState, int year, int month, int day, long minDate, 694 long maxDate) { 695 this(superState, year, month, day, minDate, maxDate, 0, 0, 0); 696 } 697 698 /** 699 * Constructor called from {@link DatePicker#onSaveInstanceState()} 700 */ 701 public SavedState(Parcelable superState, int year, int month, int day, long minDate, 702 long maxDate, int currentView, int listPosition, int listPositionOffset) { 703 super(superState); 704 mSelectedYear = year; 705 mSelectedMonth = month; 706 mSelectedDay = day; 707 mMinDate = minDate; 708 mMaxDate = maxDate; 709 mCurrentView = currentView; 710 mListPosition = listPosition; 711 mListPositionOffset = listPositionOffset; 712 } 713 714 /** 715 * Constructor called from {@link #CREATOR} 716 */ 717 private SavedState(Parcel in) { 718 super(in); 719 mSelectedYear = in.readInt(); 720 mSelectedMonth = in.readInt(); 721 mSelectedDay = in.readInt(); 722 mMinDate = in.readLong(); 723 mMaxDate = in.readLong(); 724 mCurrentView = in.readInt(); 725 mListPosition = in.readInt(); 726 mListPositionOffset = in.readInt(); 727 } 728 729 @Override 730 public void writeToParcel(Parcel dest, int flags) { 731 super.writeToParcel(dest, flags); 732 dest.writeInt(mSelectedYear); 733 dest.writeInt(mSelectedMonth); 734 dest.writeInt(mSelectedDay); 735 dest.writeLong(mMinDate); 736 dest.writeLong(mMaxDate); 737 dest.writeInt(mCurrentView); 738 dest.writeInt(mListPosition); 739 dest.writeInt(mListPositionOffset); 740 } 741 742 public int getSelectedDay() { 743 return mSelectedDay; 744 } 745 746 public int getSelectedMonth() { 747 return mSelectedMonth; 748 } 749 750 public int getSelectedYear() { 751 return mSelectedYear; 752 } 753 754 public long getMinDate() { 755 return mMinDate; 756 } 757 758 public long getMaxDate() { 759 return mMaxDate; 760 } 761 762 public int getCurrentView() { 763 return mCurrentView; 764 } 765 766 public int getListPosition() { 767 return mListPosition; 768 } 769 770 public int getListPositionOffset() { 771 return mListPositionOffset; 772 } 773 774 @SuppressWarnings("all") 775 // suppress unused and hiding 776 public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() { 777 778 public SavedState createFromParcel(Parcel in) { 779 return new SavedState(in); 780 } 781 782 public SavedState[] newArray(int size) { 783 return new SavedState[size]; 784 } 785 }; 786 } 787 } 788 789 /** 790 * A callback interface for updating input validity when the date picker 791 * when included into a dialog. 792 * 793 * @hide 794 */ 795 public interface ValidationCallback { 796 void onValidationChanged(boolean valid); 797 } 798 799 @Override 800 public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) { 801 // This view is self-sufficient for autofill, so it needs to call 802 // onProvideAutoFillStructure() to fill itself, but it does not need to call 803 // dispatchProvideAutoFillStructure() to fill its children. 804 structure.setAutofillId(getAutofillId()); 805 onProvideAutofillStructure(structure, flags); 806 } 807 808 @Override 809 public void autofill(AutofillValue value) { 810 if (!isEnabled()) return; 811 812 mDelegate.autofill(value); 813 } 814 815 @Override 816 public @AutofillType int getAutofillType() { 817 return isEnabled() ? AUTOFILL_TYPE_DATE : AUTOFILL_TYPE_NONE; 818 } 819 820 @Override 821 public AutofillValue getAutofillValue() { 822 return isEnabled() ? mDelegate.getAutofillValue() : null; 823 } 824 } 825