Vertical (垂直) Seekbar

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" />

效果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值