// Show either Hours or Minutes.
  private void setCurrentItemShowing(
      int index, boolean animateCircle, boolean delayLabelAnimate, boolean announce) {
    mTimePicker.setCurrentItemShowing(index, animateCircle);

    TextView labelToAnimate;
    if (index == HOUR_INDEX) {
      int hours = mTimePicker.getHours();
      if (!mIs24HourMode) {
        hours = hours % 12;
      }
      mTimePicker.setContentDescription(mHourPickerDescription + ": " + hours);
      if (announce) {
        Utils.tryAccessibilityAnnounce(mTimePicker, mSelectHours);
      }
      labelToAnimate = mHourView;
    } else {
      int minutes = mTimePicker.getMinutes();
      mTimePicker.setContentDescription(mMinutePickerDescription + ": " + minutes);
      if (announce) {
        Utils.tryAccessibilityAnnounce(mTimePicker, mSelectMinutes);
      }
      labelToAnimate = mMinuteView;
    }

    int hourColor = (index == HOUR_INDEX) ? mSelectedColor : mUnselectedColor;
    int minuteColor = (index == MINUTE_INDEX) ? mSelectedColor : mUnselectedColor;
    mHourView.setTextColor(hourColor);
    mMinuteView.setTextColor(minuteColor);

    ObjectAnimator pulseAnimator = Utils.getPulseAnimator(labelToAnimate, 0.85f, 1.1f);
    if (delayLabelAnimate) {
      pulseAnimator.setStartDelay(PULSE_ANIMATOR_DELAY);
    }
    pulseAnimator.start();
  }
 private void updateAmPmDisplay(int amOrPm) {
   if (amOrPm == AM) {
     mAmPmTextView.setText(mAmText);
     Utils.tryAccessibilityAnnounce(mTimePicker, mAmText);
     mAmPmHitspace.setContentDescription(mAmText);
   } else if (amOrPm == PM) {
     mAmPmTextView.setText(mPmText);
     Utils.tryAccessibilityAnnounce(mTimePicker, mPmText);
     mAmPmHitspace.setContentDescription(mPmText);
   } else {
     mAmPmTextView.setText(mDoublePlaceholderText);
   }
 }
  private boolean addKeyIfLegal(int keyCode) {
    // If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode,
    // we'll need to see if AM/PM have been typed.
    if ((mIs24HourMode && mTypedTimes.size() == 4) || (!mIs24HourMode && isTypedTimeFullyLegal())) {
      return false;
    }

    mTypedTimes.add(keyCode);
    if (!isTypedTimeLegalSoFar()) {
      deleteLastTypedKey();
      return false;
    }

    int val = getValFromKeyCode(keyCode);
    Utils.tryAccessibilityAnnounce(mTimePicker, String.format("%d", val));
    // Automatically fill in 0's if AM or PM was legally entered.
    if (isTypedTimeFullyLegal()) {
      if (!mIs24HourMode && mTypedTimes.size() <= 3) {
        mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
        mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
      }
      mDoneButton.setEnabled(true);
    }

    return true;
  }
 // If the newly selected month / year does not contain the currently selected day number,
 // change the selected day number to the last day of the selected month or year.
 //      e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
 //      e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
 private void adjustDayInMonthIfNeeded(int month, int year) {
   int day = mCalendar.get(Calendar.DAY_OF_MONTH);
   int daysInMonth = Utils.getDaysInMonth(month, year);
   if (day > daysInMonth) {
     mCalendar.set(Calendar.DAY_OF_MONTH, daysInMonth);
   }
 }
  private void updateDisplay(boolean announce) {
    if (mDayOfWeekView != null) {
      mDayOfWeekView.setText(
          mCalendar
              .getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault())
              .toUpperCase(Locale.getDefault()));
    }

    mSelectedMonthTextView.setText(
        mCalendar
            .getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault())
            .toUpperCase(Locale.getDefault()));
    mSelectedDayTextView.setText(DAY_FORMAT.format(mCalendar.getTime()));
    mYearView.setText(YEAR_FORMAT.format(mCalendar.getTime()));

    // Accessibility.
    long millis = mCalendar.getTimeInMillis();
    mAnimator.setDateMillis(millis);
    int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
    String monthAndDayText = DateUtils.formatDateTime(getActivity(), millis, flags);
    mMonthAndDayView.setContentDescription(monthAndDayText);

    if (announce) {
      flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
      String fullDateText = DateUtils.formatDateTime(getActivity(), millis, flags);
      Utils.tryAccessibilityAnnounce(mAnimator, fullDateText);
    }
  }
  private void setCurrentView(final int viewIndex) {
    long millis = mCalendar.getTimeInMillis();

    switch (viewIndex) {
      case MONTH_AND_DAY_VIEW:
        ObjectAnimator pulseAnimator = Utils.getPulseAnimator(mMonthAndDayView, 0.9f, 1.05f);
        if (mDelayAnimation) {
          pulseAnimator.setStartDelay(ANIMATION_DELAY);
          mDelayAnimation = false;
        }
        mDayPickerView.onDateChanged();
        if (mCurrentView != viewIndex) {
          mMonthAndDayView.setSelected(true);
          mYearView.setSelected(false);
          mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW);
          mCurrentView = viewIndex;
        }
        pulseAnimator.start();

        int flags = DateUtils.FORMAT_SHOW_DATE;
        String dayString = DateUtils.formatDateTime(getActivity(), millis, flags);
        mAnimator.setContentDescription(mDayPickerDescription + ": " + dayString);
        Utils.tryAccessibilityAnnounce(mAnimator, mSelectDay);
        break;
      case YEAR_VIEW:
        pulseAnimator = Utils.getPulseAnimator(mYearView, 0.85f, 1.1f);
        if (mDelayAnimation) {
          pulseAnimator.setStartDelay(ANIMATION_DELAY);
          mDelayAnimation = false;
        }
        mYearPickerView.onDateChanged();
        if (mCurrentView != viewIndex) {
          mMonthAndDayView.setSelected(false);
          mYearView.setSelected(true);
          mAnimator.setDisplayedChild(YEAR_VIEW);
          mCurrentView = viewIndex;
        }
        pulseAnimator.start();

        CharSequence yearString = YEAR_FORMAT.format(millis);
        mAnimator.setContentDescription(mYearPickerDescription + ": " + yearString);
        Utils.tryAccessibilityAnnounce(mAnimator, mSelectYear);
        break;
    }
  }
 private void setMinute(int value) {
   if (value == 60) {
     value = 0;
   }
   CharSequence text = String.format(Locale.getDefault(), "%02d", value);
   Utils.tryAccessibilityAnnounce(mTimePicker, text);
   mMinuteView.setText(text);
   mMinuteSpaceView.setText(text);
 }
  private void setHour(int value, boolean announce) {
    String format;
    if (mIs24HourMode) {
      format = "%02d";
    } else {
      format = "%d";
      value = value % 12;
      if (value == 0) {
        value = 12;
      }
    }

    CharSequence text = String.format(format, value);
    mHourView.setText(text);
    mHourSpaceView.setText(text);
    if (announce) {
      Utils.tryAccessibilityAnnounce(mTimePicker, text);
    }
  }
 /** Called by the picker for updating the header display. */
 @Override
 public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
   if (pickerIndex == HOUR_INDEX) {
     setHour(newValue, false);
     String announcement = String.format("%d", newValue);
     if (mAllowAutoAdvance && autoAdvance) {
       setCurrentItemShowing(MINUTE_INDEX, true, true, false);
       announcement += ". " + mSelectMinutes;
     } else {
       mTimePicker.setContentDescription(mHourPickerDescription + ": " + newValue);
     }
     Utils.tryAccessibilityAnnounce(mTimePicker, announcement);
   } else if (pickerIndex == MINUTE_INDEX) {
     setMinute(newValue);
     mTimePicker.setContentDescription(mMinutePickerDescription + ": " + newValue);
   } else if (pickerIndex == AMPM_INDEX) {
     updateAmPmDisplay(newValue);
   } else if (pickerIndex == ENABLE_PICKER_INDEX) {
     if (!isTypedTimeFullyLegal()) {
       mTypedTimes.clear();
     }
     finishKbMode(true);
   }
 }
 /**
  * For keyboard mode, processes key events.
  *
  * @param keyCode the pressed key.
  * @return true if the key was successfully processed, false otherwise.
  */
 private boolean processKeyUp(int keyCode) {
   if (keyCode == KeyEvent.KEYCODE_ESCAPE || keyCode == KeyEvent.KEYCODE_BACK) {
     dismiss();
     return true;
   } else if (keyCode == KeyEvent.KEYCODE_TAB) {
     if (mInKbMode) {
       if (isTypedTimeFullyLegal()) {
         finishKbMode(true);
       }
       return true;
     }
   } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
     if (mInKbMode) {
       if (!isTypedTimeFullyLegal()) {
         return true;
       }
       finishKbMode(false);
     }
     if (mCallback != null) {
       mCallback.onTimeSet(
           RadialTimePickerDialog.this, mTimePicker.getHours(), mTimePicker.getMinutes());
     }
     dismiss();
     return true;
   } else if (keyCode == KeyEvent.KEYCODE_DEL) {
     if (mInKbMode) {
       if (!mTypedTimes.isEmpty()) {
         int deleted = deleteLastTypedKey();
         String deletedKeyStr;
         if (deleted == getAmOrPmKeyCode(AM)) {
           deletedKeyStr = mAmText;
         } else if (deleted == getAmOrPmKeyCode(PM)) {
           deletedKeyStr = mPmText;
         } else {
           deletedKeyStr = String.format("%d", getValFromKeyCode(deleted));
         }
         Utils.tryAccessibilityAnnounce(
             mTimePicker, String.format(mDeletedKeyFormat, deletedKeyStr));
         updateDisplay(true);
       }
     }
   } else if (keyCode == KeyEvent.KEYCODE_0
       || keyCode == KeyEvent.KEYCODE_1
       || keyCode == KeyEvent.KEYCODE_2
       || keyCode == KeyEvent.KEYCODE_3
       || keyCode == KeyEvent.KEYCODE_4
       || keyCode == KeyEvent.KEYCODE_5
       || keyCode == KeyEvent.KEYCODE_6
       || keyCode == KeyEvent.KEYCODE_7
       || keyCode == KeyEvent.KEYCODE_8
       || keyCode == KeyEvent.KEYCODE_9
       || (!mIs24HourMode
           && (keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) {
     if (!mInKbMode) {
       if (mTimePicker == null) {
         // Something's wrong, because time picker should definitely not be null.
         Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null.");
         return true;
       }
       mTypedTimes.clear();
       tryStartingKbMode(keyCode);
       return true;
     }
     // We're already in keyboard mode.
     if (addKeyIfLegal(keyCode)) {
       updateDisplay(false);
     }
     return true;
   }
   return false;
 }