Skip to content

Commit

Permalink
v1.9:
Browse files Browse the repository at this point in the history
①new feature: touch to seek;
②bug fixed.
  • Loading branch information
woxingxiao committed Feb 22, 2017
1 parent acc89e0 commit 02802a3
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 62 deletions.
4 changes: 2 additions & 2 deletions bubbleseekbar/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 25
versionCode 8
versionName "1.8"
versionCode 9
versionName "1.9"
}

buildTypes {
Expand Down
163 changes: 103 additions & 60 deletions bubbleseekbar/src/main/java/com/xw/repo/BubbleSeekBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public class BubbleSeekBar extends View {
private boolean isShowSectionMark; // 是否显示份数
private boolean isAutoAdjustSectionMark; // 是否自动滑到最近的整份数,以showSectionMark为前提
private boolean isShowProgressInFloat; // 是否显示小数形式progress,所有小数均保留1位
private boolean isTouchToSeek; // 是否点击快速seek

private int mDelta; // max - min
private float mThumbCenterX; // thumb的中心X坐标
Expand All @@ -99,6 +100,7 @@ public class BubbleSeekBar extends View {
private WindowManager.LayoutParams mLayoutParams;
private int[] mPoint = new int[2];
private long mAnimDuration = 200;
private boolean isTouchToSeekAnimEnd = true;

public BubbleSeekBar(Context context) {
this(context, null);
Expand Down Expand Up @@ -148,6 +150,7 @@ public BubbleSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
isShowProgressInFloat = a.getBoolean(R.styleable.BubbleSeekBar_bsb_show_progress_in_float, false);
int duration = a.getInteger(R.styleable.BubbleSeekBar_bsb_anim_duration, -1);
mAnimDuration = duration < 0 ? 200 : duration;
isTouchToSeek = a.getBoolean(R.styleable.BubbleSeekBar_bsb_touch_to_seek, false);
a.recycle();

if (mMin > mMax) {
Expand Down Expand Up @@ -209,20 +212,20 @@ private void calculateRadiusOfBubble() {
// 计算滑到两端气泡里文字需要显示的宽度,比较取最大值为气泡的半径
String text = mMin < 0 ? "-" + mMin : "" + mMin;
mPaint.getTextBounds(text, 0, text.length(), mRectText);
int w1 = (mRectText.width() + mTextSpace * 2) / 2;
int w1 = (mRectText.width() + mTextSpace * 2) >> 1;
if (isShowProgressInFloat) {
text = (mMin < 0 ? "-" + mMin : mMin) + ".0";
mPaint.getTextBounds(text, 0, text.length(), mRectText);
w1 = (mRectText.width() + mTextSpace * 2) / 2;
w1 = (mRectText.width() + mTextSpace * 2) >> 1;
}

text = mMax < 0 ? "-" + mMax : "" + mMax;
mPaint.getTextBounds(text, 0, text.length(), mRectText);
int w2 = (mRectText.width() + mTextSpace * 2) / 2;
int w2 = (mRectText.width() + mTextSpace * 2) >> 1;
if (isShowProgressInFloat) {
text = (mMax < 0 ? "-" + mMax : mMax) + ".0";
mPaint.getTextBounds(text, 0, text.length(), mRectText);
w2 = (mRectText.width() + mTextSpace * 2) / 2;
w2 = (mRectText.width() + mTextSpace * 2) >> 1;
}

mBubbleRadius = dp2px(14); // 默认半径14dp
Expand Down Expand Up @@ -306,7 +309,7 @@ protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

float x1 = getPaddingLeft();
float x2 = getWidth() - getPaddingRight();
float x2 = getMeasuredWidth() - getPaddingRight();
float y = getPaddingTop() + mThumbRadiusOnDragging;

if (isShowText) {
Expand Down Expand Up @@ -352,7 +355,7 @@ protected void onDraw(Canvas canvas) {
mThumbCenterX = mTrackLength / mDelta * (mProgress - mMin) + x1;
}

if (isShowThumbText && !isThumbOnDragging) {
if (isShowThumbText && !isThumbOnDragging && isTouchToSeekAnimEnd) {
// 排除显示小数实时值、首尾文字在Bottom时,滑到首尾的情况(不会与首尾文字重合,故索性不显示)
if (mTextPosition == SIDES || !isShowProgressInFloat ||
((int) mProgress != mMin && (int) mProgress != mMax)) {
Expand Down Expand Up @@ -424,9 +427,23 @@ public boolean onTouchEvent(MotionEvent event) {
case MotionEvent.ACTION_DOWN:
isThumbOnDragging = isThumbTouched(event);
if (isThumbOnDragging) {
showBubble();
invalidate();
} else if (isTouchToSeek && isTrackTouched(event)) {
mThumbCenterX = event.getX();
if (mThumbCenterX < mLeft) {
mThumbCenterX = mLeft;
}
if (mThumbCenterX > mRight) {
mThumbCenterX = mRight;
}
mProgress = (mThumbCenterX - mLeft) * mDelta / mTrackLength + mMin;
mBubbleCenterRawX = mBubbleCenterRawSolidX + mTrackLength * (mProgress - mMin) / mDelta;

showBubble();
invalidate();
}

dx = mThumbCenterX - event.getX();

break;
Expand Down Expand Up @@ -459,31 +476,47 @@ public boolean onTouchEvent(MotionEvent event) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (isAutoAdjustSectionMark) {
autoAdjustSection();
} else if (isThumbOnDragging) {
mBubbleView.animate().alpha(0f).setDuration(mAnimDuration)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
hideBubble();

isThumbOnDragging = false;
invalidate();

if (mProgressListener != null) {
mProgressListener.getProgressOnFinally(getProgress());
mProgressListener.getProgressOnFinally(getProgressInFloat());
}
}

@Override
public void onAnimationCancel(Animator animation) {
hideBubble();

isThumbOnDragging = false;
invalidate();
}
}).start();
if (isTouchToSeek) {
mBubbleView.postDelayed(new Runnable() {
@Override
public void run() {
isTouchToSeekAnimEnd = false;
autoAdjustSection();
}
}, 300);
} else {
autoAdjustSection();
}
} else if (isThumbOnDragging || isTouchToSeek) {
mBubbleView.postDelayed(new Runnable() {
@Override
public void run() {
mBubbleView.animate().alpha(0f).setDuration(mAnimDuration)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
hideBubble();

isThumbOnDragging = false;
invalidate();

if (mProgressListener != null) {
mProgressListener.getProgressOnFinally(getProgress());
mProgressListener.getProgressOnFinally(getProgressInFloat());
}
}

@Override
public void onAnimationCancel(Animator animation) {
hideBubble();

isThumbOnDragging = false;
invalidate();
}
}).start();

}
}, !isThumbOnDragging && isTouchToSeek ? 300 : 0);

if (mProgressListener != null) {
mProgressListener.getProgressOnActionUp(getProgress());
Expand All @@ -494,19 +527,27 @@ public void onAnimationCancel(Animator animation) {
break;
}

return isThumbOnDragging || super.onTouchEvent(event);
return isThumbOnDragging || isTouchToSeek || super.onTouchEvent(event);
}

/**
* 识别thumb是否被有效点击
*/
private boolean isThumbTouched(MotionEvent event) {
float x = mTrackLength / mDelta * (mProgress - mMin) + mLeft;
float y = getHeight() / 2f;
float y = getMeasuredHeight() / 2f;
return (event.getX() - x) * (event.getX() - x) + (event.getY() - y) * (event.getY() - y)
<= (mLeft + dp2px(8)) * (mLeft + dp2px(8));
}

/**
* 识别track是否被有效点击
*/
private boolean isTrackTouched(MotionEvent event) {
return event.getX() >= getPaddingLeft() && event.getX() <= getMeasuredWidth() - getPaddingRight()
&& event.getY() >= getPaddingTop() && event.getY() <= getPaddingTop() + mThumbRadiusOnDragging * 2;
}

/**
* 显示气泡
* 原理是利用WindowManager动态添加一个与Toast相同类型的BubbleView,消失时再移除
Expand Down Expand Up @@ -543,6 +584,8 @@ public void onAnimationStart(Animator animation) {
mWindowManager.addView(mBubbleView, mLayoutParams);
}
}).start();
mBubbleView.setProgressText(isShowProgressInFloat ?
String.valueOf(getProgressInFloat()) : String.valueOf(getProgress()));
}

/**
Expand Down Expand Up @@ -610,6 +653,7 @@ public void onAnimationEnd(Animator animation) {

mProgress = (mThumbCenterX - mLeft) * mDelta / mTrackLength + mMin;
isThumbOnDragging = false;
isTouchToSeekAnimEnd = true;
invalidate();

if (mProgressListener != null) {
Expand All @@ -624,6 +668,7 @@ public void onAnimationCancel(Animator animation) {

mProgress = (mThumbCenterX - mLeft) * mDelta / mTrackLength + mMin;
isThumbOnDragging = false;
isTouchToSeekAnimEnd = true;
invalidate();
}
});
Expand Down Expand Up @@ -689,34 +734,24 @@ public int getMin() {
return mMin;
}

public void setMin(int min) {
if (mMin == min || min > mMax) {
return;
}

mMin = min;
mDelta = mMax - mMin;

calculateRadiusOfBubble();

postInvalidate();
}

public int getMax() {
return mMax;
}

public void setMax(int max) {
if (mMax == max || max < mMin) {
return;
}
public void setProgressRange(int min, int max) {
setProgressRange(min, max, getProgressInFloat());
}

mMax = max;
public void setProgressRange(int min, int max, float progress) {
mMin = Math.min(min, max);
mMax = Math.max(min, max);
mDelta = mMax - mMin;

if (mProgress > mMax) {
if (progress > mMax) {
mProgress = mMax;
}
if (progress < mMin) {
mProgress = mMin;
}
calculateRadiusOfBubble();

postInvalidate();
Expand Down Expand Up @@ -983,6 +1018,14 @@ public void setShowProgressInFloat(boolean showProgressInFloat) {
}
}

public boolean isTouchToSeek() {
return isTouchToSeek;
}

public void setTouchToSeek(boolean touchToSeek) {
isTouchToSeek = touchToSeek;
}

@ColorInt
public int getBubbleColor() {
return mBubbleColor;
Expand Down Expand Up @@ -1144,27 +1187,27 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(3 * mBubbleRadius, 3 * mBubbleRadius);

mBubbleRectF.set(getWidth() / 2f - mBubbleRadius, 0,
getWidth() / 2f + mBubbleRadius, 2 * mBubbleRadius);
mBubbleRectF.set(getMeasuredWidth() / 2f - mBubbleRadius, 0,
getMeasuredWidth() / 2f + mBubbleRadius, 2 * mBubbleRadius);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

mBubblePath.reset();
float x0 = getWidth() / 2f;
float y0 = getHeight() - mBubbleRadius / 3f;
float x0 = getMeasuredWidth() / 2f;
float y0 = getMeasuredHeight() - mBubbleRadius / 3f;
mBubblePath.moveTo(x0, y0);
float x1 = (float) (getWidth() / 2f - Math.sqrt(3) / 2f * mBubbleRadius);
float x1 = (float) (getMeasuredWidth() / 2f - Math.sqrt(3) / 2f * mBubbleRadius);
float y1 = 3 / 2f * mBubbleRadius;
mBubblePath.quadTo(
x1 - dp2px(2), y1 - dp2px(2),
x1, y1
);
mBubblePath.arcTo(mBubbleRectF, 150, 240);

float x2 = (float) (getWidth() / 2f + Math.sqrt(3) / 2f * mBubbleRadius);
float x2 = (float) (getMeasuredWidth() / 2f + Math.sqrt(3) / 2f * mBubbleRadius);
mBubblePath.quadTo(
x2 + dp2px(2), y1 - dp2px(2),
x0, y0
Expand All @@ -1179,7 +1222,7 @@ protected void onDraw(Canvas canvas) {
mBubblePaint.getTextBounds(mProgressText, 0, mProgressText.length(), mRect);
Paint.FontMetrics fm = mBubblePaint.getFontMetrics();
float baseline = mBubbleRadius + (fm.descent - fm.ascent) / 2f - fm.descent;
canvas.drawText(mProgressText, getWidth() / 2f, baseline, mBubblePaint);
canvas.drawText(mProgressText, getMeasuredWidth() / 2f, baseline, mBubblePaint);
}

void setProgressText(String progressText) {
Expand Down
1 change: 1 addition & 0 deletions bubbleseekbar/src/main/res/values/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
<attr name="bsb_auto_adjust_section_mark" format="boolean"/>
<attr name="bsb_show_progress_in_float" format="boolean"/>
<attr name="bsb_anim_duration" format="integer"/>
<attr name="bsb_touch_to_seek" format="boolean"/>
</declare-styleable>
</resources>

0 comments on commit 02802a3

Please sign in to comment.