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)暴露给使用者的是一个事件的接口,包括点击开始,点击暂停,自动到达最大时间结束,这些事件可以通过接口回调做自己的需要的交互处理
最后,附上效果图,证明代码的实用性(外圆和内圆的哪些白色为项目自己的影响,无需考虑,控件本身是没有的):
这张为默认未开始点击状态:
这张为点击开始时进度在走的状态:
这张为点击暂停的状态:
这张为进度走完自动结束的状态:
over,这个自定义的控件就给大家了,希望有需要的人可以给你有所帮助。。。
see you