예제 #1
0
  /**
   * When scroll forward/backward events are received, jump the time to the higher/lower discrete,
   * visible value on the circle.
   */
  @SuppressLint("NewApi")
  @Override
  public boolean performAccessibilityAction(int action, Bundle arguments) {
    if (super.performAccessibilityAction(action, arguments)) {
      return true;
    }

    int changeMultiplier = 0;
    if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {
      changeMultiplier = 1;
    } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
      changeMultiplier = -1;
    }
    if (changeMultiplier != 0) {
      int value = getCurrentlyShowingValue();
      int stepSize = 0;
      int currentItemShowing = getCurrentItemShowing();
      if (currentItemShowing == HOUR_INDEX) {
        stepSize = HOUR_VALUE_TO_DEGREES_STEP_SIZE;
        value %= 12;
      } else if (currentItemShowing == MINUTE_INDEX) {
        stepSize = MINUTE_VALUE_TO_DEGREES_STEP_SIZE;
      }

      int degrees = value * stepSize;
      degrees = snapOnly30s(degrees, changeMultiplier);
      value = degrees / stepSize;
      int maxValue = 0;
      int minValue = 0;
      if (currentItemShowing == HOUR_INDEX) {
        if (mIs24HourMode) {
          maxValue = 23;
        } else {
          maxValue = 12;
          minValue = 1;
        }
      } else {
        maxValue = 55;
      }
      if (value > maxValue) {
        // If we scrolled forward past the highest number, wrap around to the lowest.
        value = minValue;
      } else if (value < minValue) {
        // If we scrolled backward past the lowest number, wrap around to the highest.
        value = maxValue;
      }
      setItem(currentItemShowing, value);
      mListener.onValueSelected(currentItemShowing, value, false);
      return true;
    }

    return false;
  }
예제 #2
0
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    final float eventX = event.getX();
    final float eventY = event.getY();
    int degrees;
    int value;
    final Boolean[] isInnerCircle = new Boolean[1];
    isInnerCircle[0] = false;

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        if (!mInputEnabled) {
          return true;
        }

        mDownX = eventX;
        mDownY = eventY;

        mLastValueSelected = -1;
        mDoingMove = false;
        mDoingTouch = true;
        // If we're showing the AM/PM, check to see if the user is touching it.
        if (!mHideAmPm) {
          mIsTouchingAmOrPm = mAmPmCirclesView.getIsTouchingAmOrPm(eventX, eventY);
        } else {
          mIsTouchingAmOrPm = -1;
        }
        if (mIsTouchingAmOrPm == AM || mIsTouchingAmOrPm == PM) {
          // If the touch is on AM or PM, set it as "touched" after the TAP_TIMEOUT
          // in case the user moves their finger quickly.
          mHapticFeedbackController.tryVibrate();
          mDownDegrees = -1;
          mHandler.postDelayed(
              new Runnable() {
                @Override
                public void run() {
                  mAmPmCirclesView.setAmOrPmPressed(mIsTouchingAmOrPm);
                  mAmPmCirclesView.invalidate();
                }
              },
              TAP_TIMEOUT);
        } else {
          // If we're in accessibility mode, force the touch to be legal. Otherwise,
          // it will only register within the given touch target zone.
          boolean forceLegal = mAccessibilityManager.isTouchExplorationEnabled();
          // Calculate the degrees that is currently being touched.
          mDownDegrees = getDegreesFromCoords(eventX, eventY, forceLegal, isInnerCircle);
          if (mDownDegrees != -1) {
            // If it's a legal touch, set that number as "selected" after the
            // TAP_TIMEOUT in case the user moves their finger quickly.
            mHapticFeedbackController.tryVibrate();
            mHandler.postDelayed(
                new Runnable() {
                  @Override
                  public void run() {
                    mDoingMove = true;
                    int value = reselectSelector(mDownDegrees, isInnerCircle[0], false, true);
                    mLastValueSelected = value;
                    mListener.onValueSelected(getCurrentItemShowing(), value, false);
                  }
                },
                TAP_TIMEOUT);
          }
        }
        return true;
      case MotionEvent.ACTION_MOVE:
        if (!mInputEnabled) {
          // We shouldn't be in this state, because input is disabled.
          Log.e(TAG, "Input was disabled, but received ACTION_MOVE.");
          return true;
        }

        float dY = Math.abs(eventY - mDownY);
        float dX = Math.abs(eventX - mDownX);

        if (!mDoingMove && dX <= TOUCH_SLOP && dY <= TOUCH_SLOP) {
          // Hasn't registered down yet, just slight, accidental movement of finger.
          break;
        }

        // If we're in the middle of touching down on AM or PM, check if we still are.
        // If so, no-op. If not, remove its pressed state. Either way, no need to check
        // for touches on the other circle.
        if (mIsTouchingAmOrPm == AM || mIsTouchingAmOrPm == PM) {
          mHandler.removeCallbacksAndMessages(null);
          int isTouchingAmOrPm = mAmPmCirclesView.getIsTouchingAmOrPm(eventX, eventY);
          if (isTouchingAmOrPm != mIsTouchingAmOrPm) {
            mAmPmCirclesView.setAmOrPmPressed(-1);
            mAmPmCirclesView.invalidate();
            mIsTouchingAmOrPm = -1;
          }
          break;
        }

        if (mDownDegrees == -1) {
          // Original down was illegal, so no movement will register.
          break;
        }

        // We're doing a move along the circle, so move the selection as appropriate.
        mDoingMove = true;
        mHandler.removeCallbacksAndMessages(null);
        degrees = getDegreesFromCoords(eventX, eventY, true, isInnerCircle);
        if (degrees != -1) {
          value = reselectSelector(degrees, isInnerCircle[0], false, true);
          if (value != mLastValueSelected) {
            mHapticFeedbackController.tryVibrate();
            mLastValueSelected = value;
            mListener.onValueSelected(getCurrentItemShowing(), value, false);
          }
        }
        return true;
      case MotionEvent.ACTION_UP:
        if (!mInputEnabled) {
          // If our touch input was disabled, tell the listener to re-enable us.
          Log.d(TAG, "Input was disabled, but received ACTION_UP.");
          mListener.onValueSelected(ENABLE_PICKER_INDEX, 1, false);
          return true;
        }

        mHandler.removeCallbacksAndMessages(null);
        mDoingTouch = false;

        // If we're touching AM or PM, set it as selected, and tell the listener.
        if (mIsTouchingAmOrPm == AM || mIsTouchingAmOrPm == PM) {
          int isTouchingAmOrPm = mAmPmCirclesView.getIsTouchingAmOrPm(eventX, eventY);
          mAmPmCirclesView.setAmOrPmPressed(-1);
          mAmPmCirclesView.invalidate();

          if (isTouchingAmOrPm == mIsTouchingAmOrPm) {
            mAmPmCirclesView.setAmOrPm(isTouchingAmOrPm);
            if (getIsCurrentlyAmOrPm() != isTouchingAmOrPm) {
              mListener.onValueSelected(AMPM_INDEX, mIsTouchingAmOrPm, false);
              setValueForItem(AMPM_INDEX, isTouchingAmOrPm);
            }
          }
          mIsTouchingAmOrPm = -1;
          break;
        }

        // If we have a legal degrees selected, set the value and tell the listener.
        if (mDownDegrees != -1) {
          degrees = getDegreesFromCoords(eventX, eventY, mDoingMove, isInnerCircle);
          if (degrees != -1) {
            value = reselectSelector(degrees, isInnerCircle[0], !mDoingMove, false);
            if (getCurrentItemShowing() == HOUR_INDEX && !mIs24HourMode) {
              int amOrPm = getIsCurrentlyAmOrPm();
              if (amOrPm == AM && value == 12) {
                value = 0;
              } else if (amOrPm == PM && value != 12) {
                value += 12;
              }
            }
            setValueForItem(getCurrentItemShowing(), value);
            mListener.onValueSelected(getCurrentItemShowing(), value, true);
          }
        }
        mDoingMove = false;
        return true;
      default:
        break;
    }
    return false;
  }