项目地址.
这一篇我们主要是完成自定义录制RecordView
,页面很简单,就长下面那样,我们点击一下是拍照,按住就开始录制,录制需要进度条,进度条满或者松手表示录制完成
首先我们定义几个属性
<declare-styleable name="RecordView">
//进度条颜色
<attr name="progress_color" format="color">attr>
//进度条宽度
<attr name="progress_width" format="dimension">attr>
//按钮填充颜色
<attr name="fill_color" format="color">attr>
//按钮的半径
<attr name="radius" format="dimension">attr>
//录制的最大时长
<attr name="duration" format="integer">attr>
declare-styleable>
接着我们在构造方法中获取到这些属性
public class RecordView extends View {
private int progressMaxValue;
private final int radius;
private final int progressWidth;
private final int progressColor;
private final int fillColor;
private final int maxDuration;
private int progressValue;
public RecordView(Context context) {
this(context, null);
}
public RecordView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RecordView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public RecordView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordView, defStyleAttr, defStyleRes);
radius = typedArray.getDimensionPixelOffset(R.styleable.RecordView_radius, 0);
progressWidth = typedArray.getDimensionPixelOffset(R.styleable.RecordView_progress_width, PixUtils.dp2px(3));
progressColor = typedArray.getColor(R.styleable.RecordView_progress_color, Color.RED);
fillColor = typedArray.getColor(R.styleable.RecordView_fill_color, Color.WHITE);
maxDuration = typedArray.getInteger(R.styleable.RecordView_duration, 10);
setMaxDuration(maxDuration);
typedArray.recycle();
}
}
然后我们定义两个画笔`Paint
private final Paint fillPaint;
private final Paint progressPaint;
fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
fillPaint.setColor(fillColor);
fillPaint.setStyle(Paint.Style.FILL);
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressPaint.setColor(progressColor);
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setStrokeWidth(progressWidth);
然后我们就要区分是拍照还是录视频了,拍照只有下面一个圆形,录制视频还有一个进度条,我们在onDraw
方法中实现
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
if (isRecording) {
canvas.drawCircle(width / 2, height / 2, width / 2, fillPaint);
int left = progressWidth / 2;
int top = progressWidth / 2;
int right = width - progressWidth / 2;
int bottom = height - progressWidth / 2;
float sweepAngle = (progressValue * 1.0f / progressMaxValue) * 360;
canvas.drawArc(left, top, right, bottom, -90, sweepAngle, false, progressPaint);
} else {
canvas.drawCircle(width / 2, height / 2, radius, fillPaint);
}
}
接着我们就是需要监听点击事件和长按事件,这是使用setOnTouchListener
,监听按下和抬起的时间来判断
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isRecording = true;
startRecordTime = System.currentTimeMillis();
handler.sendEmptyMessage(0);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
long now = System.currentTimeMillis();
if (now - startRecordTime > ViewConfiguration.getLongPressTimeout()) {
finishRecord();
}
handler.removeCallbacksAndMessages(null);
isRecording = false;
startRecordTime = 0;
progressValue = 0;
postInvalidate();
}
return false;
}
});
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressValue++;
postInvalidate();
if (progressValue <= progressMaxValue) {
sendEmptyMessageDelayed(0, PROGRESS_INTERVAL);
} else {
finishRecord();
}
}
};
我们这里是在录制的时候只要没录制完,每隔100毫秒重新刷新下进度条
最后我们再通过接口的形式把事件传递出去
public interface onRecordListener {
void onClick();
void onLongClick();
void onFinish();
}
`