微信视频的录制按钮
接上面的文章把微信的录制写完整
涉及到知识点主要是以下:
1.手势监控的类GestureDetectorCompat支持更多的手势
2.设置自定义的属性
3.handler实现的倒计时操作
下面简单介绍绘制的流程,绘制控件分成几个步骤来做
- 自定义属性分为三步:
1.在values下面创建attrs.xml文件,里面定义自定义的属性名称和属性的限制类型
<declare-styleable name="LProgressBar">
<attr name="innerColor" format="color" />
<attr name="outerColor" format="color" />
<attr name="progressColor" format="color" />
<attr name="innerRadio" format="dimension" />
<attr name="progressWidth" format="dimension" />
<attr name="maxSecond" format="integer" />
</declare-styleable>
2.在xml文件中使用这个自定义的属性:
<com.example.lxrent.camerademo.view.LProgressBar
android:id="@+id/tv"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
app:innerColor="@android:color/white"
app:innerRadio="55dp"
app:maxSecond="5"
app:outerColor="@android:color/darker_gray"
app:progressColor="@android:color/holo_green_light"
app:progressWidth="10dp" />
3.再自定义的类中找到属性并获取属性使用:
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LProgressBar);
innerColor = a.getColor(R.styleable.LProgressBar_innerColor, innerColor);
outerColor = a.getColor(R.styleable.LProgressBar_outerColor, outerColor);
progressColor = a.getColor(R.styleable.LProgressBar_progressColor, progressColor);
innerRadio = a.getDimension(R.styleable.LProgressBar_innerRadio, innerRadio);
progressWidth = a.getDimensionPixelOffset(R.styleable.LProgressBar_progressWidth, progressWidth);
maxSecond = a.getInt(R.styleable.LProgressBar_maxSecond, maxSecond)*100;//默认扩大100倍
a.recycle();
}
- 手势的识别操作的主要类GestureDetector,不过如果我们只需要使用部分的手势的话可以用GestureDetectorCompat来实现,下面写上代码:
mDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
isLongClick = false;
if (LProgressBar.this.listener != null) {
LProgressBar.this.listener.onClick(LProgressBar.this);
}
return super.onSingleTapUp(e);
}
@Override
public void onLongPress(MotionEvent e) {
//长按可以处理不断绘制
isLongClick = true;
if (LProgressBar.this.listener != null) {
LProgressBar.this.listener.onLongClick(LProgressBar.this);
}
mHandler.postDelayed(task, 0);
}
});
- 下面是介绍绘制的主要流程,主要思路是默认是让外圆半径和内圆半径缩小一定比例,在长按的手势事件触发后,内圆半径变大,外圆半径变小
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//确定圆心
float circle = getWidth() / 2.0f;
if (!isLongClick) {
//绘制外圆
canvas.drawCircle(circle, circle, outerRadio * 0.7f, backgroundPaint);
//绘制内圆
canvas.drawCircle(circle, circle, innerRadio * 0.7f, innerPaint);
} else {
//绘制外圆
canvas.drawCircle(circle, circle, outerRadio, backgroundPaint);
//绘制内圆
canvas.drawCircle(circle, circle, innerRadio * 0.4f, innerPaint);
}
rectF = new RectF(progressWidth / 2, progressWidth / 2, outerRadio * 2 - progressWidth / 2, outerRadio * 2 - progressWidth / 2);
//绘制进度条
sweepAngle = ((float) progress / maxSecond) * 360;
canvas.drawArc(rectF, startAngle, sweepAngle, false, progressPaint);
}
上面基本上介绍了大多数的流程了,其实也是贴代码,毕竟控件很简单,没什么可说的,最后把整个类的代码放上,有需要的可以直接copy走。
public class LProgressBar extends View {
/**
* 内圆颜色
*/
private int innerColor = Color.WHITE;
/**
* 外圈颜色
*/
private int outerColor = Color.GRAY;
/**
* 进度颜色
*/
private int progressColor = Color.parseColor("#00FF00");
/**
* 进条度宽
*/
private int progressWidth = 5;
/**
* 外圆半径
*/
private int outerRadio = 60;
/**
* 内圆半径
*/
private float innerRadio = outerRadio* 0.7f;
/**
* 外圈 进度 内圈 paint
*/
private Paint backgroundPaint, progressPaint, innerPaint;
/**
* 手势时事件
*/
private GestureDetectorCompat mDetector;
/**
* 是否为长按录制
*/
private boolean isLongClick;
private RectF rectF;
private float startAngle = -90;
private float sweepAngle;
private int progress = 0;
/**
* 默认是10秒
*/
private int maxSecond = 1000;
private Handler mHandler = new Handler();
private Runnable task = new Runnable() {
@Override
public void run() {
progress++;
if (progress > maxSecond) {
reset();
if (listener != null) {
listener.onLongClickUp(LProgressBar.this);
}
return;
}
invalidate();
mHandler.postDelayed(task, 10);
}
};
public LProgressBar(Context context) {
super(context);
init(context, null);
}
public LProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public LProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LProgressBar);
innerColor = a.getColor(R.styleable.LProgressBar_innerColor, innerColor);
outerColor = a.getColor(R.styleable.LProgressBar_outerColor, outerColor);
progressColor = a.getColor(R.styleable.LProgressBar_progressColor, progressColor);
innerRadio = a.getDimension(R.styleable.LProgressBar_innerRadio, innerRadio);
progressWidth = a.getDimensionPixelOffset(R.styleable.LProgressBar_progressWidth, progressWidth);
maxSecond = a.getInt(R.styleable.LProgressBar_maxSecond, maxSecond)*100;//默认扩大100倍
Log.i("eeeeeeeee",a.getIndexCount()+"");
a.recycle();
}
backgroundPaint = new Paint();
backgroundPaint.setAntiAlias(true);
backgroundPaint.setColor(outerColor);
progressPaint = new Paint();
progressPaint.setAntiAlias(true);
progressPaint.setStrokeWidth(progressWidth);
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setColor(progressColor);
innerPaint = new Paint();
innerPaint.setAntiAlias(true);
innerPaint.setColor(innerColor);
mDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
isLongClick = false;
if (LProgressBar.this.listener != null) {
LProgressBar.this.listener.onClick(LProgressBar.this);
}
return super.onSingleTapUp(e);
}
@Override
public void onLongPress(MotionEvent e) {
//长按可以处理不断绘制
isLongClick = true;
if (LProgressBar.this.listener != null) {
LProgressBar.this.listener.onLongClick(LProgressBar.this);
}
mHandler.postDelayed(task, 0);
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (width > height) {
setMeasuredDimension(height, height);
outerRadio = height / 2;
} else {
setMeasuredDimension(width, width);
outerRadio = width / 2;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//确定圆心
float circle = getWidth() / 2.0f;
if (!isLongClick) {
//绘制外圆
canvas.drawCircle(circle, circle, outerRadio * 0.7f, backgroundPaint);
//绘制内圆
canvas.drawCircle(circle, circle, innerRadio * 0.7f, innerPaint);
} else {
//绘制外圆
canvas.drawCircle(circle, circle, outerRadio, backgroundPaint);
//绘制内圆
canvas.drawCircle(circle, circle, innerRadio * 0.4f, innerPaint);
}
rectF = new RectF(progressWidth / 2, progressWidth / 2, outerRadio * 2 - progressWidth / 2, outerRadio * 2 - progressWidth / 2);
//绘制进度条
sweepAngle = ((float) progress / maxSecond) * 360;
canvas.drawArc(rectF, startAngle, sweepAngle, false, progressPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
this.mDetector.onTouchEvent(event);
switch (MotionEventCompat.getActionMasked(event)) {
case MotionEvent.ACTION_DOWN:
isLongClick = false;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (isLongClick) {
isLongClick = false;
if (LProgressBar.this.listener != null) {
LProgressBar.this.listener.onLongClickUp(LProgressBar.this);
}
reset();
}
break;
}
return true;
}
/**
* 还原到初始状态
*/
public void reset() {
isLongClick = false;
this.progress = 0;
this.sweepAngle = 0;
mHandler.removeCallbacks(task);
invalidate();
}
private OnProgressTouchListener listener;
public void setOnProgressTouchListener(OnProgressTouchListener listener) {
this.listener = listener;
}
public interface OnProgressTouchListener {
/**
* 单击
*
* @param progressBar
*/
void onClick(LProgressBar progressBar);
/**
* 长按
*
* @param progressBar
*/
void onLongClick(LProgressBar progressBar);
/**
* 长按抬起
*
* @param progressBar
*/
void onLongClickUp(LProgressBar progressBar);
}
}
结语
希望这个小控件会帮助到你