private void updateThumbPos(int posX) {
    int thumbWidth = mThumb.getIntrinsicWidth();
    int halfThumb = thumbWidth / 2;
    int start;
    if (isRtl()) {
      start = getWidth() - getPaddingRight() - mAddedTouchBounds;
      posX = start - posX - thumbWidth;
    } else {
      start = getPaddingLeft() + mAddedTouchBounds;
      posX = start + posX;
    }
    mThumb.copyBounds(mInvalidateRect);
    mThumb.setBounds(posX, mInvalidateRect.top, posX + thumbWidth, mInvalidateRect.bottom);
    if (isRtl()) {
      mScrubber.getBounds().right = start - halfThumb;
      mScrubber.getBounds().left = posX + halfThumb;
    } else {
      mScrubber.getBounds().left = start + halfThumb;
      mScrubber.getBounds().right = posX + halfThumb;
    }
    final Rect finalBounds = mTempRect;
    mThumb.copyBounds(finalBounds);
    if (!isInEditMode()) {
      mIndicator.move(finalBounds.centerX());
    }

    mInvalidateRect.inset(-mAddedTouchBounds, -mAddedTouchBounds);
    finalBounds.inset(-mAddedTouchBounds, -mAddedTouchBounds);
    mInvalidateRect.union(finalBounds);
    SeekBarCompat.setHotspotBounds(
        mRipple, finalBounds.left, finalBounds.top, finalBounds.right, finalBounds.bottom);
    invalidate(mInvalidateRect);
  }
 private void showFloater() {
   if (!isInEditMode()) {
     mThumb.animateToPressed();
     mIndicator.showIndicator(this, mThumb.getBounds());
     notifyBubble(true);
   }
 }
 private boolean startDragging(MotionEvent ev, boolean ignoreTrackIfInScrollContainer) {
   final Rect bounds = mTempRect;
   mThumb.copyBounds(bounds);
   // Grow the current thumb rect for a bigger touch area
   bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds);
   mIsDragging = (bounds.contains((int) ev.getX(), (int) ev.getY()));
   if (!mIsDragging && mAllowTrackClick && !ignoreTrackIfInScrollContainer) {
     // If the user clicked outside the thumb, we compute the current position
     // and force an immediate drag to it.
     mIsDragging = true;
     mDragOffset = (bounds.width() / 2) - mAddedTouchBounds;
     updateDragging(ev);
     // As the thumb may have moved, get the bounds again
     mThumb.copyBounds(bounds);
     bounds.inset(-mAddedTouchBounds, -mAddedTouchBounds);
   }
   if (mIsDragging) {
     setPressed(true);
     attemptClaimDrag();
     setHotspot(ev.getX(), ev.getY());
     mDragOffset = (int) (ev.getX() - bounds.left - mAddedTouchBounds);
     if (mPublicChangeListener != null) {
       mPublicChangeListener.onStartTrackingTouch(this);
     }
   }
   return mIsDragging;
 }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    int thumbWidth = mThumb.getIntrinsicWidth();
    int thumbHeight = mThumb.getIntrinsicHeight();
    int addedThumb = mAddedTouchBounds;
    int halfThumb = thumbWidth / 2;
    int paddingLeft = getPaddingLeft() + addedThumb;
    int paddingRight = getPaddingRight();
    int bottom = getHeight() - getPaddingBottom() - addedThumb;
    mThumb.setBounds(paddingLeft, bottom - thumbHeight, paddingLeft + thumbWidth, bottom);
    int trackHeight = Math.max(mTrackHeight / 2, 1);
    mTrack.setBounds(
        paddingLeft + halfThumb,
        bottom - halfThumb - trackHeight,
        getWidth() - halfThumb - paddingRight - addedThumb,
        bottom - halfThumb + trackHeight);
    int scrubberHeight = Math.max(mScrubberHeight / 2, 2);
    mScrubber.setBounds(
        paddingLeft + halfThumb,
        bottom - halfThumb - scrubberHeight,
        paddingLeft + halfThumb,
        bottom - halfThumb + scrubberHeight);

    // Update the thumb position after size changed
    updateThumbPosFromCurrentProgress();
  }
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   int widthSize = MeasureSpec.getSize(widthMeasureSpec);
   int height = mThumb.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom();
   height += (mAddedTouchBounds * 2);
   setMeasuredDimension(widthSize, height);
 }
 /**
  * Sets the color of the seek thumb, as well as the color of the popup indicator.
  *
  * @param thumbColorStateList The ColorStateList the seek thumb will be changed to
  * @param indicatorColor The color the popup indicator will be changed to The indicator will
  *     animate from thumbColorStateList(pressed state) to indicatorColor when opening
  */
 public void setThumbColor(@NonNull ColorStateList thumbColorStateList, int indicatorColor) {
   mThumb.setColorStateList(thumbColorStateList);
   // we use the "pressed" color to morph the indicator from it to its own color
   int thumbColor =
       thumbColorStateList.getColorForState(
           new int[] {PRESSED_STATE}, thumbColorStateList.getDefaultColor());
   mIndicator.setColors(indicatorColor, thumbColor);
 }
 @Override
 protected synchronized void onDraw(Canvas canvas) {
   if (!isLollipopOrGreater) {
     mRipple.draw(canvas);
   }
   super.onDraw(canvas);
   mTrack.draw(canvas);
   mScrubber.draw(canvas);
   mThumb.draw(canvas);
 }
  private void updateThumbPosFromCurrentProgress() {
    int thumbWidth = mThumb.getIntrinsicWidth();
    int addedThumb = mAddedTouchBounds;
    int halfThumb = thumbWidth / 2;
    float scaleDraw = (mValue - mMin) / (float) (mMax - mMin);

    // This doesn't matter if RTL, as we just need the "avaiable" area
    int left = getPaddingLeft() + halfThumb + addedThumb;
    int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb);
    int available = right - left;

    final int thumbPos = (int) (scaleDraw * available + 0.5f);
    updateThumbPos(thumbPos);
  }
 private void updateProgressFromAnimation(float scale) {
   Rect bounds = mThumb.getBounds();
   int halfThumb = bounds.width() / 2;
   int addedThumb = mAddedTouchBounds;
   int left = getPaddingLeft() + halfThumb + addedThumb;
   int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb);
   int available = right - left;
   int progress = Math.round((scale * (mMax - mMin)) + mMin);
   // we don't want to just call setProgress here to avoid the animation being cancelled,
   // and this position is not bound to a real progress value but interpolated
   if (progress != getProgress()) {
     mValue = progress;
     notifyProgress(mValue, true);
     updateProgressMessage(progress);
   }
   final int thumbPos = (int) (scale * available + 0.5f);
   updateThumbPos(thumbPos);
 }
Exemplo n.º 10
0
  private void updateDragging(MotionEvent ev) {
    setHotspot(ev.getX(), ev.getY());
    int x = (int) ev.getX();
    Rect oldBounds = mThumb.getBounds();
    int halfThumb = oldBounds.width() / 2;
    int addedThumb = mAddedTouchBounds;
    int newX = x - mDragOffset + halfThumb;
    int left = getPaddingLeft() + halfThumb + addedThumb;
    int right = getWidth() - (getPaddingRight() + halfThumb + addedThumb);
    if (newX < left) {
      newX = left;
    } else if (newX > right) {
      newX = right;
    }

    int available = right - left;
    float scale = (float) (newX - left) / (float) available;
    if (isRtl()) {
      scale = 1f - scale;
    }
    int progress = Math.round((scale * (mMax - mMin)) + mMin);
    setProgress(progress, true);
  }
Exemplo n.º 11
0
 private void updateFromDrawableState() {
   int[] state = getDrawableState();
   boolean focused = false;
   boolean pressed = false;
   for (int i : state) {
     if (i == FOCUSED_STATE) {
       focused = true;
     } else if (i == PRESSED_STATE) {
       pressed = true;
     }
   }
   if (isEnabled() && (focused || pressed) && mIndicatorPopupEnabled) {
     // We want to add a small delay here to avoid
     // poping in/out on simple taps
     removeCallbacks(mShowIndicatorRunnable);
     postDelayed(mShowIndicatorRunnable, INDICATOR_DELAY_FOR_TAPS);
   } else {
     hideFloater();
   }
   mThumb.setState(state);
   mTrack.setState(state);
   mScrubber.setState(state);
   mRipple.setState(state);
 }
Exemplo n.º 12
0
 @Override
 public void onClosingComplete() {
   mThumb.animateToNormal();
 }
Exemplo n.º 13
0
 /**
  * Sets the color of the seek thumb, as well as the color of the popup indicator.
  *
  * @param thumbColor The color the seek thumb will be changed to
  * @param indicatorColor The color the popup indicator will be changed to The indicator will
  *     animate from thumbColor to indicatorColor when opening
  */
 public void setThumbColor(int thumbColor, int indicatorColor) {
   mThumb.setColorStateList(ColorStateList.valueOf(thumbColor));
   mIndicator.setColors(indicatorColor, thumbColor);
 }
Exemplo n.º 14
0
  public DiscreteSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setFocusable(true);
    setWillNotDraw(false);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    float density = context.getResources().getDisplayMetrics().density;
    mTrackHeight = (int) (1 * density);
    mScrubberHeight = (int) (4 * density);
    int thumbSize = (int) (density * ThumbDrawable.DEFAULT_SIZE_DP);

    // Extra pixels for a touch area of 48dp
    int touchBounds = (int) (density * 32);
    mAddedTouchBounds = (touchBounds - thumbSize) / 2;

    TypedArray a =
        context.obtainStyledAttributes(
            attrs, R.styleable.DiscreteSeekBar, defStyleAttr, R.style.Widget_DiscreteSeekBar);

    int max = 100;
    int min = 0;
    int value = 0;
    mMirrorForRtl = a.getBoolean(R.styleable.DiscreteSeekBar_dsb_mirrorForRtl, mMirrorForRtl);
    mAllowTrackClick =
        a.getBoolean(R.styleable.DiscreteSeekBar_dsb_allowTrackClickToDrag, mAllowTrackClick);
    mIndicatorPopupEnabled =
        a.getBoolean(R.styleable.DiscreteSeekBar_dsb_indicatorPopupEnabled, mIndicatorPopupEnabled);
    int indexMax = R.styleable.DiscreteSeekBar_dsb_max;
    int indexMin = R.styleable.DiscreteSeekBar_dsb_min;
    int indexValue = R.styleable.DiscreteSeekBar_dsb_value;
    final TypedValue out = new TypedValue();
    // Not sure why, but we wanted to be able to use dimensions here...
    if (a.getValue(indexMax, out)) {
      if (out.type == TypedValue.TYPE_DIMENSION) {
        max = a.getDimensionPixelSize(indexMax, max);
      } else {
        max = a.getInteger(indexMax, max);
      }
    }
    if (a.getValue(indexMin, out)) {
      if (out.type == TypedValue.TYPE_DIMENSION) {
        min = a.getDimensionPixelSize(indexMin, min);
      } else {
        min = a.getInteger(indexMin, min);
      }
    }
    if (a.getValue(indexValue, out)) {
      if (out.type == TypedValue.TYPE_DIMENSION) {
        value = a.getDimensionPixelSize(indexValue, value);
      } else {
        value = a.getInteger(indexValue, value);
      }
    }

    mMin = min;
    mMax = Math.max(min + 1, max);
    mValue = Math.max(min, Math.min(max, value));
    updateKeyboardRange();

    mIndicatorFormatter = a.getString(R.styleable.DiscreteSeekBar_dsb_indicatorFormatter);

    ColorStateList trackColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_trackColor);
    ColorStateList progressColor =
        a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_progressColor);
    ColorStateList rippleColor = a.getColorStateList(R.styleable.DiscreteSeekBar_dsb_rippleColor);
    boolean editMode = isInEditMode();
    if (editMode || rippleColor == null) {
      rippleColor = new ColorStateList(new int[][] {new int[] {}}, new int[] {Color.DKGRAY});
    }
    if (editMode || trackColor == null) {
      trackColor = new ColorStateList(new int[][] {new int[] {}}, new int[] {Color.GRAY});
    }
    if (editMode || progressColor == null) {
      progressColor =
          new ColorStateList(new int[][] {new int[] {}}, new int[] {DEFAULT_THUMB_COLOR});
    }
    mRipple = SeekBarCompat.getRipple(rippleColor);
    if (isLollipopOrGreater) {
      SeekBarCompat.setBackground(this, mRipple);
    } else {
      mRipple.setCallback(this);
    }

    TrackRectDrawable shapeDrawable = new TrackRectDrawable(trackColor);
    mTrack = shapeDrawable;
    mTrack.setCallback(this);

    shapeDrawable = new TrackRectDrawable(progressColor);
    mScrubber = shapeDrawable;
    mScrubber.setCallback(this);

    mThumb = new ThumbDrawable(progressColor, thumbSize);
    mThumb.setCallback(this);
    mThumb.setBounds(0, 0, mThumb.getIntrinsicWidth(), mThumb.getIntrinsicHeight());

    if (!editMode) {
      mIndicator = new PopupIndicator(context, attrs, defStyleAttr, convertValueToMessage(mMax));
      mIndicator.setListener(mFloaterListener);
    }
    a.recycle();

    setNumericTransformer(new DefaultNumericTransformer());
  }