带悬浮文字的水平SeekBar

一、概述

这是一个带悬浮文字的水平SeekBar,可以设置手指按下显示,还是一直显示悬浮文字。本来想在网上找一个框架,但是想改成自己需求的样子都差点,可能自己没搞清楚API。最后自己写了个功能简单的,有需要的拿走自己修改,废话不多说,直接上代码。

二、内容

1、效果图

2、代码

package com.yang.mytest.util;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;


/**
 * Created by yp on 2018-03-26.
 */

public class MyHorizontalSeekBar extends View {
    private Context context;
    /** 进度条宽度 */
    private float barWidth = getTextSizeDip(4);
    /** view的宽 */
    private int width;
    /** view的高 */
    private int height;
    /** seekbar总值 */
    private int maxProgress = 100;
    /** 进度条起始X坐标*/
    private float startX;
    /** 进度条起始Y坐标*/
    private float startY;
    /** 进度条当前X坐标*/
    private float dx;
    /** 进度条当前Y坐标*/
    private float dy;
    /**进度条背景画笔*/
    private Paint seekBackgroundPaint;
    /**进度条进度画笔*/
    private Paint seekProgressPaint;
    /**文字画笔*/
    private Paint textPaint;
    /**文字背景画笔*/
    private Paint textBackgroundPaint;
    /**进度点画笔*/
    private Paint seekPaint;
    /** 进度调整指数*/
    private float adjustmentFactor = getTextSizeDip(50);
    /**进度背景图层*/
    private RectF rectBg = new RectF();
    /**进度条图层*/
    private RectF rectProgress = new RectF();
    /**进度点图层*/
    private RectF rectSeek = new RectF();
    /** 底部距离*/
    private int bottom = 8;
    /** 左边距离*/
    private int left = 8;
    /** 右边距离*/
    private int right = 8;
    /** 顶部距离*/
    private int top = 8;
    /**进度条长度*/
    private int seekbarLength;
    /**进度条进度*/
    private float progress = 0f;
    /**进度点宽度*/
    private float seekWidth = getTextSizeDip(4);
    /**进度点高度*/
    private float seekHeight = getTextSizeDip(14);
    /**进度条上方文字*/
    private String progressText="01-03 10:22:02";
    /**文字距离*/
    private float textHeight = getTextSizeDip(20);
    /**文字背景宽度*/
    private float bgWidth = getTextSizeDip(110);
    /**文字背景高度*/
    private float bgHeight = getTextSizeDip(24);
    /**测试文本的规格*/
    private Paint.FontMetrics fm;
    /** 是否手指按下的标志位 */
    private boolean isPressed = false;
    /**进度监听*/
    private onChangeListener listener;


    public MyHorizontalSeekBar(Context context) {
        super(context);
    }

    public MyHorizontalSeekBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public MyHorizontalSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        startX = getPaddingLeft() + left;
        startY = height - bottom - barWidth/2;
        dx = startX + seekbarLength * progress/100f;
        dy = startY;
        seekbarLength = width - getPaddingRight() - getPaddingLeft() - left - right;
        rectBg.set(startX,height - bottom - barWidth,width-right-getPaddingRight(),height - bottom);
    }

    private void init(){
        seekBackgroundPaint = new Paint();
        seekBackgroundPaint.setAntiAlias(true);
        seekBackgroundPaint.setStrokeWidth(1);
        seekBackgroundPaint.setColor(Color.parseColor("#d2d7d7"));
        seekBackgroundPaint.setStyle(Paint.Style.FILL);

        seekProgressPaint = new Paint();
        seekProgressPaint.setAntiAlias(true);
        seekProgressPaint.setStrokeWidth(1);
        seekProgressPaint.setColor(Color.parseColor("#00bf8f"));
        seekProgressPaint.setStyle(Paint.Style.FILL);

        textBackgroundPaint = new Paint();
        textBackgroundPaint.setAntiAlias(true);
        textBackgroundPaint.setStrokeWidth(1);
        textBackgroundPaint.setColor(Color.parseColor("#d2d7d7"));
        textBackgroundPaint.setStyle(Paint.Style.FILL);

        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setStrokeWidth(1);
        textPaint.setTextSize(getTextSizeDip(12));
        textPaint.setColor(Color.parseColor("#4d5e58"));

        seekPaint = new Paint();
        seekPaint.setAntiAlias(true);
        seekPaint.setStrokeWidth(1);
        seekPaint.setColor(Color.parseColor("#00bf8f"));
        seekPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制背景
        canvas.drawRoundRect(rectBg,4,4,seekBackgroundPaint);
        //绘制进度
        drawSeekProgress(canvas);
        //绘制进度点
        drawSeekMark(canvas);
        //绘制文字及文字背景
        if(isPressed){//需要按下才显示
//            drawTextBackground(canvas);
        }
        drawTextBackground(canvas);
    }

    /**
     * 绘制进度条
     */
    private void drawSeekProgress(Canvas canvas){
        rectProgress.set(startX,height - bottom - barWidth,startX + seekbarLength * progress/100f,height - bottom);
        canvas.drawRoundRect(rectProgress,4,4,seekProgressPaint);
    }

    /**
     * 绘制进度点
     * @param canvas
     */
    private void drawSeekMark(Canvas canvas){
        dx = startX + seekbarLength * progress/100f;
        rectSeek.set(dx - seekWidth/2f,dy - seekHeight/2f,dx + seekWidth/2f,
                dy + seekHeight/2f);
        canvas.drawRect(rectSeek,seekPaint);
    }

    /**
     * 设置文字和文字背景区域
     */
    private void drawTextBackground(Canvas canvas){
        fm = textPaint.getFontMetrics();
        float left = dx - bgWidth/2;
        left = left < startX ? startX : left;//超出左边距
        float right = left + bgWidth;
        right = right > (startX + seekbarLength) ? (startX + seekbarLength) : right;//超出右边距
        left = right - bgWidth;
        float top = dy - textHeight - bgHeight - barWidth/2;
        float bottom = dy - textHeight - barWidth/2;

        canvas.drawRect(left,top,right,bottom,textBackgroundPaint);

        float textWidth = textPaint.measureText(progressText);
        float textY = bottom - bgHeight/2 - fm.descent/2 - fm.ascent/2;
        float textX = dx - textWidth/2;
        float textLeftX = startX + bgWidth/2 - textWidth/2;
        float textRight = startX + seekbarLength - bgWidth/2 - textWidth/2;
        textX = textX < textLeftX ? textLeftX : textX;
        textX = textX > textRight ? textRight : textX;

        canvas.drawText(progressText, textX,textY,textPaint);
    }

    /**
     * 重写onTouch方法
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        boolean up = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_MOVE:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_UP:
                up = true;
                moved(x, y, up);
                break;
        }
        return true;
    }

    private void moved(float x, float y, boolean up){
        float distanceX = Math.abs(x - dx);
        float distanceY = Math.abs(y - dy);
        if(distanceX < adjustmentFactor && distanceY <adjustmentFactor && !up){
            isPressed = true;
            dx = x;
            dx = dx < startX ? startX : dx;
            dx = dx > startX + seekbarLength ? startX + seekbarLength : dx;
            float val = (dx - startX) * 10000/seekbarLength;
            progress = ((int)val)/100f;
            if(listener != null) listener.onChange(progress);
            invalidate();
        }else{
            isPressed = false;
            invalidate();
        }
    }

    private float getTextSizePX(float value){
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, value, getResources().getDisplayMetrics());
    }

    private float getTextSizeDip(float value){
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
    }

    public interface onChangeListener{
        public void onChange(float progress);
    }

    public void setListener(onChangeListener listener) {
        this.listener = listener;
    }

    public float getProgress() {
        return progress;
    }

    public void setProgress(float progress) {
        this.progress = progress;
        invalidate();
    }

    public String getProgressText() {
        return progressText;
    }

    public void setProgressText(String progressText) {
        this.progressText = progressText;
        invalidate();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值