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); }
@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(); }
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); }
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()); }