Android自定义可拖动进度条

如题,看效果图:



该自定义组件的优势:

1、使用简单;

2、可随意改变圆点、直线的颜色和大小;


当然,也许你会吐槽,系统不是提供了 seekBar 吗,怎么不用 seekBar。

我想说,我写这个也是一时来了兴致,因为最近在研究自定义组件,根据自己项目里的需求,自己写出来的。虽然DEMO不是很高大上,但内心还是很欣喜的。所以,还希望嘴上留情。

还是那句话,你可以不爱,但请不要伤害。


直接晒代码


package com.junhui.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.ColorRes;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.junhui.R;

/**
 * 可触摸进度视图
 * <p>
 * Created by 晖仔(Milo) on 2017/2/20.
 * email:303767416@qq.com
 */

public class TouchProgressView extends View {
    private static final String TAG = "TouchProgressView";

    private Paint linePaint;
    private Paint pointPaint;

    private int pointRadius = 10;//圆点默认半径,单位px
    private int pointColor = R.color.gray_dft;//圆点默认颜色

    private int lineHeight = 2;//线默认高度,单位px
    private int lineClor = R.color.gray_dft;//线默认颜色

    private int progress = 0;
    private final int PROGRESS_MIN = 0;
    private final int PROGRESS_MAX = 100;

    private OnProgressChangedListener progressChangedListener;

    public interface OnProgressChangedListener {
        void onProgressChanged(View view, int progress);
    }

    public TouchProgressView(Context context) {
        super(context, null);
    }

    public TouchProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TouchProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 设置圆点半径
     *
     * @param radius
     */
    public void setPointRadius(final int radius) {
        if (radius <= 0) {
            throw new IllegalArgumentException("radius 不可以小于等于0");
        }

        if (getWidth() == 0) {
            post(new Runnable() {
                @Override
                public void run() {
                    if (radius * 2 > getWidth()) {
                        throw new IllegalArgumentException("radius*2 必须小于 view.getWidth() == " + getWidth());
                    }
                    pointRadius = radius;
                }
            });
        } else {
            if (radius * 2 > getWidth()) {
                throw new IllegalArgumentException("radius*2 必须小于 view.getWidth() == " + getWidth());
            }
            this.pointRadius = radius;
        }
    }

    /**
     * 设置圆点颜色
     *
     * @param color
     */
    public void setPointColor(@ColorRes int color) {
        this.pointColor = color;
    }

    /**
     * 设置直线高度
     *
     * @param height
     */
    public void setLineHeight(int height) {
        if (height <= 0) {
            throw new IllegalArgumentException("height 不可以小于等于0");
        }

        this.lineHeight = height;
    }

    /**
     * 设置直线颜色
     *
     * @param color
     */
    public void setLineColor(@ColorRes int color) {
        this.lineClor = color;
    }

    /**
     * 设置百分比
     *
     * @param progress
     */
    public void setProgress(int progress) {
        if (progress < 0 || progress > 100) {
            throw new IllegalArgumentException("progress 不可以小于0 或大于100");
        }
        this.progress = progress;
        invalidate();

        if (progressChangedListener != null) {
            progressChangedListener.onProgressChanged(this, progress);
        }
    }

    /**
     * 设置进度变化监听器
     *
     * @param onProgressChangedListener
     */
    public void setOnProgressChangedListener(OnProgressChangedListener onProgressChangedListener) {
        this.progressChangedListener = onProgressChangedListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getX() < pointRadius) {
            setProgress(PROGRESS_MIN);
            return true;
        } else if (event.getX() > getWidth() - pointRadius) {
            setProgress(PROGRESS_MAX);
            return true;
        } else {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    setProgress(calculProgress(event.getX()));
                    return true;
                case MotionEvent.ACTION_MOVE:
                    setProgress(calculProgress(event.getX()));
                    return true;
            }
        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public void draw(Canvas canvas) {
        Log.d(TAG, "[draw] .. in .. ");
        super.draw(canvas);

        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setStrokeWidth(lineHeight);
        linePaint.setColor(getResources().getColor(lineClor));

        //因为是以画布Canvas 为draw对象,所以RectF构造函数内的参数是以canvas为边界,而不是屏幕
        canvas.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2, linePaint);

        pointPaint = new Paint();
        pointPaint.setAntiAlias(true);
        pointPaint.setStyle(Paint.Style.FILL);
        pointPaint.setColor(getResources().getColor(pointColor));
        canvas.drawCircle(getCx(), getHeight() / 2, pointRadius, pointPaint);
    }

    /**
     * 获取圆点的x轴坐标
     *
     * @return
     */
    private float getCx() {
        float cx = 0.0f;
        cx = (getWidth() - pointRadius * 2);
        if (cx < 0) {
            throw new IllegalArgumentException("TouchProgressView 宽度不可以小于 2 倍 pointRadius");
        }
        return cx / 100 * progress + pointRadius;
    }

    /**
     * 计算触摸点的百分比
     *
     * @param eventX
     * @return
     */
    private int calculProgress(float eventX) {
        float proResult = (eventX - pointRadius) / (getWidth() - pointRadius * 2);
        return (int) (proResult * 100);
    }

}


以上就是完整代码,有不懂的可以留言提问,看到就会回答的。


DEMO下载地址:


Git: https://github.com/yanjunhui2014/TouchProgressView

CSDN:http://download.csdn.net/detail/yanjunhui2011/9758893


原创不易,转载记得附源自: http://write.blog.csdn.net/postedit/56016414



评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值