jQuery鼠标指针特效

带进度条的控件--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;
    }
}

原作者,参考链接

posted @ 2022-07-12 11:47  僵小七  阅读(46)  评论(0编辑  收藏  举报