ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

带进度条的控件--CircleProcessView

2022-07-12 12:04:04  阅读:122  来源: 互联网

标签:控件 20 -- private currentProgress int circlePaint import CircleProcessView


CircleProcessView

package com.example.myapplication.demoUI;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;

import androidx.appcompat.widget.AppCompatImageView;

import com.example.myapplication.R;

/**
 * 1.初始化画笔,测量
 * 2.确定位置绘制图形
 * 3.处理点击事件
 * 4.编写接口,暴露方法给外部
 */
public class PausePressView extends AppCompatImageView {
    private Paint circlePaint;
    private int defaultWidth, defaultHeight;

    public PausePressView(Context context) {
        this(context, null);
    }

    public PausePressView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PausePressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
        setPadding(20, 20, 20, 20);
    }

    @SuppressLint("ResourceAsColor")
    private void initPaint() {
        circlePaint = new Paint();
        circlePaint.setColor(getContext().getResources().getColor(R.color.c_FF6E66));
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setAntiAlias(true);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);//笔帽
        circlePaint.setStrokeWidth(5);
    }


    /*
     * 测量模式	  **   视图的赋值方式	**        描述
     * UNSPECIFIED **	MATCH_PARENT	**  与上一级视图大小一样
     *   AT_MOST	  **   WRAP_CONTENT	    **  包裹其自身内容(按照自身尺寸进行适配)
     * EXACTLY	  **    整型数值	        **   设置尺寸的数值
     *
     *   //获取父 View 的测量模式
     *    int specMode = MeasureSpec.getMode(measureSpec);
     *    //获取父 View 的测量尺寸
     *    int specSize = MeasureSpec.getSize(measureSpec);
     * */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        ViewGroup.LayoutParams layoutParams = this.getLayoutParams();
        if (layoutParams != null) {
            defaultHeight = layoutParams.height;
            defaultWidth = layoutParams.width;
        }
        //获取到图片资源的大小,然后设置大小
        setMeasuredDimension(defaultWidth, defaultHeight);


    }

    //换算 测量控件宽、高
    private int de_width = 20, de_height = 20;

    protected int measureDimension(int defaultSize, int measureSpec) {
        int result = defaultSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        //1. layout给出了确定的值,比如:100dp
        //2. layout使用的是match_parent,但父控件的size已经可以确定了,
        // 比如设置的是具体的值或者match_parent
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize; //建议:result直接使用确定值
        }
        //1. layout使用的是wrap_content
        //2. layout使用的是match_parent,但父控件使用的是确定的值或者wrap_content
        else if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(defaultSize, specSize); //建议:result不能大于specSize
        }
        //UNSPECIFIED,没有任何限制,所以可以设置任何大小
        //多半出现在自定义的父控件的情况下,期望由自定义自行决定大小
        else {
            result = defaultSize;
        }
        return result;
    }


    RectF rect;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int measuredWidth = getMeasuredWidth();
        int measuredHeight = getMeasuredHeight();

        if (rect == null) {
            rect = new RectF(10, 10, measuredWidth - 10, measuredHeight - 10);
        }

        circlePaint.setColor(getContext().getResources().getColor(R.color.c_FFE7E6));
        //绘制底线
        canvas.drawArc(rect, -90, 360, false, circlePaint);
        circlePaint.setColor(getContext().getResources().getColor(R.color.c_FF6E66));
        //绘制前景线
        canvas.drawArc(rect, -90, currentProgress, false, circlePaint);
    }

    //倒计时的时长
    private int countDownDuration = 2;

    //当前的进度
    private float currentProgress = 0;

    //手是否有释放
    private boolean isRelease = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                //start
                this.isRelease = false;
                this.setImageResource(R.drawable.zuye_yinyue_bofan_d);
                startCountDown();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                //end
                this.isRelease = true;
                //告诉外部
                if (currentProgress < 360 && mOnCountDownStateChangeListener != null) {
                    mOnCountDownStateChangeListener.onCountDownCancel();
                }
                break;
        }
        //消费掉此事件
        return true;
    }

    private void startCountDown() {
        if (this.currentProgress >= 360) {
            this.currentProgress = 0;
        }
        //换算成毫秒
        int duration;
        if (!isRelease) {
            duration = countDownDuration * 1000;
        } else {
            //往回倒时只要1秒的动画即可
            duration = 1000;
        }
        //第20毫秒绘制一次进度
        int rate = duration / 20;
        //求度数
        float perDegree = 360 * 1.0f / rate;
        //The runnable will be run on the user interface thread.
        post(new Runnable() {
            @Override
            public void run() {
                if (!isRelease) {
                    currentProgress += perDegree;
                } else {
                    currentProgress -= perDegree;
                }
                if (currentProgress < 0) {
                    currentProgress = 0;
                }
                if (currentProgress >= 360) {
                    //结束了
                    currentProgress = 360;
                    //TODO:告诉外部
                    if (mOnCountDownStateChangeListener != null) {
                        mOnCountDownStateChangeListener.onCountDownEnd();
                    }
                }
                //重新绘制
                invalidate();
                if (currentProgress > 0 && currentProgress < 360) {
                    postDelayed(this, 20);
                }
            }
        });
    }


    private OnCountDownStateChangeListener mOnCountDownStateChangeListener;

    //定义接口 暴露方法
    public interface OnCountDownStateChangeListener{
        //end
        void onCountDownEnd();

        //cancel
        void onCountDownCancel();
    }

    public void setOnCountDownStateChangeListener(OnCountDownStateChangeListener listener) {
        this.mOnCountDownStateChangeListener = listener;
    }
}

原作者,参考链接

标签:控件,20,--,private,currentProgress,int,circlePaint,import,CircleProcessView
来源: https://www.cnblogs.com/kato-T/p/16469552.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有