自定义属性 来实现 ProgressBar 圆形进度条

来源:互联网 发布:淘宝显示原价和折扣价 编辑:程序博客网 时间:2024/06/11 21:07

实现圆形进度条的拖拽,点击实现效果如下图所示:

圆形进度条拖拽点击

自定义属性

在src/values中新建attrs.xml
<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="XProgressBar">        <attr name="progress" format="integer"/>        <attr name="max" format="integer"/>        <attr name="smallCircleColor" format="color"/>        <attr name="progressColor" format="color"/>        <attr name="textColor" format="color"/>        <attr name="borderOutWidth" format="dimension"/>    </declare-styleable></resources>

在主布局中引用自定义属性

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.xykj.xprogressbar.MainActivity"    android:orientation="vertical">    <com.xykj.view.XProgressBar        android:layout_width="match_parent"        android:layout_height="100dp"        app:progress="30"        app:progressColor="@color/colorAccent"/>    <com.xykj.view.XSeekBar        android:layout_width="match_parent"        android:layout_height="300dp"        android:layout_marginTop="10dp"/></LinearLayout>

定义类XProgressBar继承View

public class XProgressBar extends View {    protected int radius;    //小圆半径    private int smallRadius;    //中心点    protected Point center;    //当前进度    protected int progress;    //总进度    protected int max = 100;    //外部的进度的宽度    private int borderOutWidth = 20;    //内部小圆的颜色    private int smallCircleColor = 0xff00A2E8;    //进度的颜色    private int progressColor = 0xff22B14C;    //文本颜色    private int textColor = 0xFFFFFFFF;    //画笔    private Paint paint;    //进度弧度所在的矩形区域    private RectF progressRect;    public XProgressBar(Context context) {        super(context);        init();    }    public XProgressBar(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.XProgressBar);        progress = ta.getInteger(R.styleable.XProgressBar_progress, 0);        max = ta.getInteger(R.styleable.XProgressBar_max, 100);        borderOutWidth = ta.getDimensionPixelSize(R.styleable.XProgressBar_borderOutWidth, 20);        smallCircleColor = ta.getColor(R.styleable.XProgressBar_smallCircleColor, 0xff00A2E8);        progressColor = ta.getColor(R.styleable.XProgressBar_progressColor, 0xff22B14C);        textColor = ta.getColor(R.styleable.XProgressBar_textColor, 0xffffffff);        ta.recycle();        init();    }    private void init() {        center = new Point();        progressRect = new RectF();        //初始化画笔        paint = new Paint();        paint.setAntiAlias(true);        paint.setStrokeWidth(borderOutWidth);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = getDefaultSize(80, widthMeasureSpec);        int height = getDefaultSize(80, heightMeasureSpec);        //记录中心点        center.set(width / 2, height / 2);        //取小的一边作为显示的最大半径        radius = width > height ? center.y : center.x;        progressRect.set(center.x - radius + borderOutWidth / 2,                center.y - radius + borderOutWidth / 2,                center.x + radius - borderOutWidth / 2,                center.y + radius - borderOutWidth / 2);        if (smallRadius == 0) {            smallRadius = radius - borderOutWidth - 3;            paint.setTextSize(smallRadius / 2);        }        setMeasuredDimension(width, height);    }    public static int getDefaultSize(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            int specSize = MeasureSpec.getSize(measureSpec);            if (specSize > size) {                result = specSize;            }        }        return result;    }    Rect textRect = new Rect();    @Override    protected void onDraw(Canvas canvas) {        //画小圆背景(实心)        paint.setStyle(Paint.Style.FILL);        paint.setColor(smallCircleColor);        canvas.drawCircle(center.x, center.y, smallRadius, paint);        //画文本        String text = progress + "%";  //0% 50% 100%        paint.getTextBounds(text, 0, text.length(), textRect);        paint.setColor(textColor);        canvas.drawText(text, center.x - textRect.centerX(),                center.y - textRect.centerY(), paint);        //画进度的弧度        paint.setStyle(Paint.Style.STROKE);        paint.setColor(progressColor);        int degress = getDegress();        canvas.drawArc(progressRect, -90, degress, false, paint);    }    protected int getDegress(){        return 360 * progress / max;    }    public int getProgress() {        return progress;    }    public void setProgress(int progress) {        if (this.progress != progress && progress <= max) {            this.progress = progress;            invalidate();        }    }    public int getMax() {        return max;    }    public void setMax(int max) {        this.max = max;    }    public int getBorderOutWidth() {        return borderOutWidth;    }    public void setBorderOutWidth(int borderOutWidth) {        this.borderOutWidth = borderOutWidth;    }    public int getSmallCircleColor() {        return smallCircleColor;    }    public void setSmallCircleColor(int smallCircleColor) {        if(this.smallCircleColor != smallCircleColor) {            this.smallCircleColor = smallCircleColor;            invalidate();        }    }    public int getProgressColor() {        return progressColor;    }    public void setProgressColor(int progressColor) {        if(this.progressColor != progressColor) {            this.progressColor = progressColor;            invalidate();        }    }    public int getTextColor() {        return textColor;    }    public void setTextColor(int textColor) {        if(this.textColor != textColor) {            this.textColor = textColor;            invalidate();        }    }}

定义类XSeekBar继承XProgressBar

public class XSeekBar extends XProgressBar {    public XSeekBar(Context context) {        super(context);    }    public XSeekBar(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    private int degress;    @Override    public boolean onTouchEvent(MotionEvent event) {        int action = event.getAction();        switch (action) {            case MotionEvent.ACTION_DOWN:                if (null != onXSeekBarChangeListener) {                    onXSeekBarChangeListener.onStartTrackingTouch(this);                }            case MotionEvent.ACTION_MOVE:                float x = event.getX();                float y = event.getY();                float dis = getDistence(x, y);                if (dis >= radius - 10 && dis <= radius + 10) {                    //在圆上,计算触控点和圆顶部切线的tan值                    float tanValue = (y - center.y + radius) / Math.abs(x - center.x);                    //反tan获取触控点和顶部切线的夹角(0-2PI)                    float dPi = (float) Math.atan(tanValue);                    //触控点和顶部切线夹角的2倍即为弧度角                    int d = (int) Math.toDegrees(dPi);                    if (x < center.x) {                        d = 180 - d;                    }                    degress = d * 2;                    if (degress > 360) {                        degress = 360;                    } else if (degress < 0) {                        degress = 0;                    }                    progress = max * degress / 360;                    if (null != onXSeekBarChangeListener) {                        onXSeekBarChangeListener.onProgressChanged(this, progress, true);                    }                    invalidate();                }                break;            case MotionEvent.ACTION_UP:                if (null != onXSeekBarChangeListener) {                    onXSeekBarChangeListener.onStopTrackingTouch(this);                }                break;        }        return true;    }    /**     * 计算触控点到圆心的距离     *     * @param x     * @param y     * @return     */    private float getDistence(float x, float y) {        return (float) Math.sqrt(Math.pow(x - center.x, 2) + Math.pow(y - center.y, 2));    }    @Override    protected int getDegress() {        return degress;    }    @Override    public void setProgress(int progress) {        if (this.progress != progress && null != onXSeekBarChangeListener) {            onXSeekBarChangeListener.onProgressChanged(this, progress, false);        }        super.setProgress(progress);    }    public OnXSeekBarChangeListener getOnXSeekBarChangeListener() {        return onXSeekBarChangeListener;    }    public void setOnXSeekBarChangeListener(OnXSeekBarChangeListener onXSeekBarChangeListener) {        this.onXSeekBarChangeListener = onXSeekBarChangeListener;    }    private OnXSeekBarChangeListener onXSeekBarChangeListener;    public interface OnXSeekBarChangeListener {        void onStartTrackingTouch(XSeekBar bar);        void onProgressChanged(XSeekBar seekBar, int progress, boolean fromUser);        void onStopTrackingTouch(XSeekBar bar);    }}
阅读全文
0 0
原创粉丝点击