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