package com.example.testdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;
import androidx.annotation.Nullable;
public class VHSeekBar extends SeekBar {
private static final String TAG = “VHSeekBar”;
private Drawable mThumb;
private OnSeekBarChangeListener mOnSeekBarChangeListener;
public Paint mPaint;
private String mTextString;
private int chseekbarTextPadding;
public VHSeekBar(Context context) {
super(context);
initPaint(context);
}
public VHSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint(context);
}
public VHSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPaint(context);
}
private void initPaint(Context context) {
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);//去除锯齿
mPaint.setTextSize((int)context.getResources().getDimension(R.dimen.beauty_level_textsize_medium));
mPaint.setTypeface(Typeface.SANS_SERIF);
chseekbarTextPadding = (int)context.getResources().getDimension(R.dimen.chseekbar_text_padding);
Log.d(TAG, "initPaint: getheight = " + getHeight());
}
public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
mOnSeekBarChangeListener = l;
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
//倒置宽与高
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas canvas) {
Log.d(TAG, "onDraw: ");
canvas.rotate(90);
canvas.translate(0, -getWidth());
super.onDraw(canvas);
drawProgressText(canvas);
}
private void drawProgressText(Canvas canvas) {
int left = getPaddingLeft();
int top = getPaddingTop();
int right = getPaddingRight();
int bottom = getPaddingBottom();
int width = getWidth() - left - right;
int height = getHeight() - top - bottom;
Rect thumbRect = null;
if (getThumb() != null) {
thumbRect = getThumb().getBounds();
}
float thumb_x = (float)this.getProgress() * (width/ (float)this.getMax());
try {
float fontWidth = getFontlength(mPaint, mTextString);
float fontHeight = getFontHeight(mPaint);
int x = thumbRect.left + left + (int)fontHeight/2 - 2;
int y = (int)fontWidth;
canvas.rotate(-90,x,y);
canvas.drawText(mTextString, x, y, mPaint);
} catch (Exception e) {
// TODO: handle exception
}
}
public void setSeekBarText(String str)
{
mTextString = str;
invalidate();
}
public float getFontlength(Paint paint, String str) {
return paint.measureText(str);
}
/**
* @return 返回指定笔的文字高度
*/
public float getFontHeight(Paint paint) {
FontMetrics fm = paint.getFontMetrics();
return fm.descent - fm.ascent;
}
/**
* @return 返回指定笔离文字顶部的基准距离
*/
public float getFontLeading(Paint paint) {
FontMetrics fm = paint.getFontMetrics();
return fm.leading- fm.ascent;
}
private void onProgressRefresh(float scale, boolean fromUser) {
if (scale < 0) {
scale = 0;
}
if (scale > getMax()) {
scale = getMax();
}
Drawable thumb = mThumb;
if (thumb != null) {
setThumbPos(getHeight(), thumb, scale);
invalidate();
}
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
}
}
private void setThumbPos(int height, Drawable thumb, float position) {
Rect rect = getProgressDrawable().getBounds();
int available =rect.right -rect.left + getPaddingLeft();
int thumbWidth = thumb.getIntrinsicWidth();
int thumbHeight = thumb.getIntrinsicHeight();
available -= thumbHeight;
int thumbPos = (int) (position * available / getMax() + 0.5f);
if(thumbPos < rect.left) {
thumbPos = rect.left;
}
if(thumbPos > rect.right) {
thumbPos = rect.right;
}
Log.d(TAG, "setThumbPos: thumbPos = " + thumbPos + " rect.right = " + rect.right + " rect.left = " + rect.left);
int topBound, bottomBound;
Rect oldBounds = thumb.getBounds();
topBound = oldBounds.top;
bottomBound = oldBounds.bottom;
thumb.setBounds(thumbPos, topBound, thumbPos + thumbHeight, bottomBound);
getBackground().setVisible(false,false);
}
public void setThumb(Drawable thumb) {
mThumb = thumb;
super.setThumb(thumb);
}
void onStartTrackingTouch() {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStartTrackingTouch(this);
}
}
void onStopTrackingTouch() {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStopTrackingTouch(this);
}
}
private void attemptClaimDrag() {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setPressed(true);
onStartTrackingTouch();
break;
case MotionEvent.ACTION_MOVE:
int progress = getMax() - (int) (getMax() * (getHeight() - event.getY()) / getHeight());
Log.d(TAG, "onTouchEvent: progress = " + progress + " event.getY() = " + event.getY());
if(progress > getMax()) {
progress = getMax();
}
if(progress < 0) {
progress = 0;
}
setProgress(progress);
onProgressRefresh(progress, false);
attemptClaimDrag();
break;
case MotionEvent.ACTION_UP:
onStopTrackingTouch();
setPressed(false);
break;
case MotionEvent.ACTION_CANCEL:
onStopTrackingTouch();
setPressed(false);
break;
}
return true;
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
onProgressRefresh(progress, false);
}
}
Xml
<com.example.testdemo.VHSeekBar
android:id="@+id/bokeh_v_seekbar"
android:layout_width="54dp"
android:layout_height="312dp"
android:background="#55ffff00"
android:paddingTop="30dp"
android:maxHeight="1.5dp"
android:minHeight="1.5dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:max="100"
android:layout_marginStart="20dp"
android:progressDrawable="@drawable/bokeh_seekbar_progress1"
android:thumb="@drawable/century_bokeh_seekbar_thumb"
android:progressTint="#FFFFFFFF"
android:thumbTint="#FFFFFFFF"
android:focusable="true" />
效果