Android自定义视频录制时的带进度条的按钮

前言:由于项目的需要,在视频录制的时候需要点击开始的按钮带圆形进度条的功能,所以就看了网上的一些资料,基本都是长按仿微信的录制功能。

而我自己需要的是点击录制和点击的暂停,也不需要那么炫的效果,所以自定义了一个view,有需要的伙伴们可以看看,自定义厉害的大神们可以无视此博客

此view功能不算强大,但是原理简单,可以任意扩展,使用以及修改极其方便,而且注释很清晰明了

总之一句话,这个代码就是一眼看去完全懂了,你按照自己的需要想怎么改就怎么改!!


好了不废话了,直接上这个类的代码:

package com.deepblue.lanbuff.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


/**
 * 自定义的圆形进度按钮 用于录制视频页面的开始和暂停功能
 * Created by meng on 2017/11/8.
 */
public class CircleButtonView extends View {
    private Paint mBigCirclePaint;//外圈进度的背景色
    private Paint mSmallCirclePaint;//内圈圆
    private Paint mProgressCirclePaint;//外圈进度的颜色
    private Paint mInnerSquarePaint;//内圈的正方形

    /**
     * 自定义使用的颜色资源id
     */
    private int mBigCircleColorId=0;//外圈进度的背景色
    private int mSmallCircleId=0;//内圈圆形的颜色
    private int mProgressCircleId=0;//外圈进度条的颜色
    private int mInnerSquareId=0;//内圈的正方形的颜色

    private int mHeight;//当前View的高
    private int mWidth;//当前View的宽
    private float mBigRadius;//外圈大圆的半径
    private float mSmallRadius;//内圈小圆的半径
    private boolean isRecording = false;//录制状态
    private float mCurrentProgress = 0;//当前进度

    private int maxTime = 120;//录制最大时间s
    private float mProgressW = 17f;//圆环宽度

    public OnButtonStatusChangeListener listener;

    public CircleButtonView(Context context) {
        super(context);
        init(context, null);
    }

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

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

    private void init(Context context, AttributeSet attrs) {
        //初始画笔抗锯齿、颜色
        mBigCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (mBigCircleColorId!=0){
            mBigCirclePaint.setColor(getResources().getColor(mBigCircleColorId));
        }else{
            mBigCirclePaint.setColor(getResources().getColor(android.R.color.white));
        }

        mSmallCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (mSmallCircleId!=0){
            mSmallCirclePaint.setColor(getResources().getColor(mSmallCircleId));
        }else{
            mSmallCirclePaint.setColor(getResources().getColor(android.R.color.holo_orange_dark));
        }

        mProgressCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (mProgressCircleId!=0){
            mProgressCirclePaint.setColor(getResources().getColor(mProgressCircleId));
        }else{
            mProgressCirclePaint.setColor(getResources().getColor(android.R.color.holo_orange_dark));
        }

        mInnerSquarePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (mInnerSquareId!=0){
            mInnerSquarePaint.setColor(getResources().getColor(mInnerSquareId));
        }else{
            mInnerSquarePaint.setColor(getResources().getColor(android.R.color.white));
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
        mBigRadius = mWidth / 2;
        mSmallRadius = mBigRadius * 0.75f;
    }

    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);
        //绘制外圆的进度条的背景
        drawProgressBackground(canvas);

        //绘制内圆
        canvas.drawCircle(mWidth / 2, mHeight / 2, mSmallRadius, mSmallCirclePaint);

        //绘制里面的正方形
        if (isRecording) {
            canvas.drawRect(mWidth / 3, mHeight / 3, mWidth - mWidth / 3, mHeight - mHeight / 3, mInnerSquarePaint);
        }

        //录制的过程中绘制进度条
        drawProgress(canvas);
    }

    /**
     * 绘制圆形进度
     *
     * @param canvas
     */
    private void drawProgress(Canvas canvas) {
        mProgressCirclePaint.setStrokeWidth(mProgressW);
        mProgressCirclePaint.setStyle(Paint.Style.STROKE);
        //用于定义的圆弧的形状和大小的界限
        RectF oval = new RectF(mWidth / 2 - (mBigRadius - mProgressW / 2), mHeight / 2 - (mBigRadius - mProgressW / 2),
                mWidth / 2 + (mBigRadius - mProgressW / 2), mHeight / 2 + (mBigRadius - mProgressW / 2));
        //根据进度画圆弧
        float sweepAngle = mCurrentProgress / maxTime * 360;
        canvas.drawArc(oval, -180, sweepAngle, false, mProgressCirclePaint);
    }
    /**
     * 绘制圆形进度的底色圈
     *
     * @param canvas
     */
    private void drawProgressBackground(Canvas canvas) {
        mBigCirclePaint.setStrokeWidth(mProgressW);
        mBigCirclePaint.setStyle(Paint.Style.STROKE);
        //用于定义的圆弧的形状和大小的界限
        RectF oval = new RectF(mWidth / 2 - (mBigRadius - mProgressW / 2), mHeight / 2 - (mBigRadius - mProgressW / 2),
                mWidth / 2 + (mBigRadius - mProgressW / 2), mHeight / 2 + (mBigRadius - mProgressW / 2));
        canvas.drawArc(oval, 0, 360, false, mBigCirclePaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isRecording = !isRecording;
                invalidate();
                if (isRecording) {//开始播放
                    mHandler.sendEmptyMessageDelayed(0, 1000);
                    if (listener != null){
                        listener.onStart();
                    }
                } else {//暂停播放
                    mHandler.removeCallbacksAndMessages(null);
                    if (listener != null){
                        listener.onStop();
                    }
                }
                break;
        }
        return true;

    }

    public void setOnStatusChangeListener(OnButtonStatusChangeListener listener) {
        this.listener = listener;
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            mCurrentProgress = mCurrentProgress + 1;
            if (mCurrentProgress >= maxTime) {//进度条正在前进
                mCurrentProgress = maxTime;
                if (listener != null) {
                    listener.onFinish();
                }
                isRecording = false;
                invalidate();
            } else {//进度条走到了最大值
                this.sendEmptyMessageDelayed(0, 1000);
                invalidate();
            }
        }
    };

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mHandler!=null){
            mHandler.removeCallbacksAndMessages(null);
        }
    }


    public interface OnButtonStatusChangeListener {
        void onStart();

        void onStop();

        void onFinish();
    }

    public void setMaxTime(int maxTime) {
        this.maxTime = maxTime;
    }

    public void setmProgressW(float mProgressW) {
        if (mProgressW>maxTime){
            return;
        }
        this.mProgressW = mProgressW;
    }

    public float getmCurrentProgress() {
        return mCurrentProgress;
    }

    public void setmCurrentProgress(float mCurrentProgress) {
        this.mCurrentProgress = mCurrentProgress;
    }

    public void setmBigCircleColorId(int mBigCircleColorId) {
        this.mBigCircleColorId = mBigCircleColorId;
    }

    public void setmSmallCircleId(int mSmallCircleId) {
        this.mSmallCircleId = mSmallCircleId;
    }

    public void setmProgressCircleId(int mProgressCircleId) {
        this.mProgressCircleId = mProgressCircleId;
    }

    public void setmInnerSquareId(int mInnerSquareId) {
        this.mInnerSquareId = mInnerSquareId;
    }
}

厉害的伙伴一眼如果代码就看懂了,就不需要看下面的了,因为下面的内容是对该类功能的简单介绍,方便游客的使用


这个自定义的控件有如下的功能和扩展:

(1)控件的最外边是圆形的进度条,背景色和进度条颜色可以set方法修改默认的

(2)里边是圆形的图形和一个小的正方形,这两个图形的颜色都可以通过set方法进行修改

(3)外边的圆形和里面的圆形中间的空隙是透明的,如果不想透明,请自行修改

(4)暴露给使用者的是一个事件的接口,包括点击开始,点击暂停,自动到达最大时间结束,这些事件可以通过接口回调做自己的需要的交互处理


最后,附上效果图,证明代码的实用性(外圆和内圆的哪些白色为项目自己的影响,无需考虑,控件本身是没有的):


这张为默认未开始点击状态:Android自定义视频录制时的带进度条的按钮


这张为点击开始时进度在走的状态:Android自定义视频录制时的带进度条的按钮


这张为点击暂停的状态:Android自定义视频录制时的带进度条的按钮


这张为进度走完自动结束的状态:Android自定义视频录制时的带进度条的按钮


over,这个自定义的控件就给大家了,希望有需要的人可以给你有所帮助。。。


              see you