Android实现微信拍照按钮
2023-08-07 本文已影响0人
不会弹钢琴de大叔
由于项目需要,做了一个自定义View实现了点击拍照,长按录像的功能,有相应的回调事件,见如下代码:
public class CircleButtonView extends View {
private static final int WHAT_LONG_CLICK = 1;
private static final int WHAT_RECORD_VIDEO = 2;
private Paint mPaint;
private Paint mBarPaint;
private Paint mTextPaint;
private int mWidth;
private float mStrokeWidth;
private long mStartTime;
private boolean isRecording, isPressed;
private float mCurrentProgress;
private final int updateTime = 50;
private final int longClickTime = 150;
private int curTime;
private OnClickListener clickListener;
private OnLongClickListener longClickListener;
private Bitmap mSeatBitmap;
private String mText;
public CircleButtonView(Context context) {
super(context);
init();
}
public CircleButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public CircleButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
//初始画笔抗锯齿、颜色
mStrokeWidth = dip2px(10);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mTextPaint = new Paint();
mTextPaint.setTextSize(24);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setColor(ContextCompat.getColor(getContext(), R.color.gwm_color_main_text));
mBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBarPaint.setColor(Color.parseColor("#6ABF66"));
mBarPaint.setStrokeWidth(mStrokeWidth);
mBarPaint.setStyle(Paint.Style.STROKE);
mBarPaint.setAntiAlias(true);
mSeatBitmap = getBitmapFromDrawable(R.drawable.icon_temp_zuoyi);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mWidth = getMeasuredWidth();
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mSeatBitmap, 0, 0, mPaint);
if (isRecording) {
drawProgress(canvas);
}
canvas.drawText(mText, mWidth / 2f, mWidth + dip2px(30), mTextPaint);
}
/**
* 绘制圆形进度
*
* @param canvas
*/
private void drawProgress(Canvas canvas) {
RectF oval = new RectF(0 + mStrokeWidth / 2f, 0 + mStrokeWidth / 2f,
mWidth - mStrokeWidth / 2f, mWidth - mStrokeWidth / 2f);
canvas.drawArc(oval, -90, mCurrentProgress, false, mBarPaint);
}
@SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//长按事件触发
if (msg.what == WHAT_LONG_CLICK) {
curTime = longClickTime;
mCurrentProgress = 0;
isRecording = true;
invalidate();
sendCircle();
} else if (msg.what == WHAT_RECORD_VIDEO) {
int mRecordTime = 1000;
if (mRecordTime > curTime) {
curTime += updateTime;
mCurrentProgress = (float) 360 / mRecordTime * curTime;
invalidate();
sendCircle();
} else {
if (isPressed) {
reset();
LogUtils.logi("longClick view");
if (longClickListener != null) {
longClickListener.onLongClick(CircleButtonView.this);
}
}
}
}
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
LogUtils.logi("onTouchEvent click: start");
isPressed = true;
mStartTime = System.currentTimeMillis();
Message mMessage = Message.obtain();
mMessage.what = WHAT_LONG_CLICK;
mHandler.sendMessageDelayed(mMessage, longClickTime);
break;
case MotionEvent.ACTION_UP:
reset();
long mEndTime = System.currentTimeMillis();
if (mEndTime - mStartTime < longClickTime) {
LogUtils.logi("click view");
if (clickListener != null) {
clickListener.onClick(this);
}
}
break;
case MotionEvent.ACTION_CANCEL:
reset();
break;
default:
break;
}
return true;
}
public void setClickListener(OnClickListener clickListener) {
this.clickListener = clickListener;
}
public void setLongClickListener(OnLongClickListener longClickListener) {
this.longClickListener = longClickListener;
}
public void setViewText(String text) {
mText = text;
}
private void reset() {
isPressed = false;
isRecording = false;
mHandler.removeMessages(WHAT_LONG_CLICK);
mHandler.removeMessages(WHAT_RECORD_VIDEO);
mCurrentProgress = 0;
invalidate();
}
private void sendCircle() {
mHandler.sendEmptyMessageDelayed(WHAT_RECORD_VIDEO, updateTime);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mHandler.removeCallbacksAndMessages(null);
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
private int dip2px(float dpValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
private Bitmap getBitmapFromDrawable(@DrawableRes int drawableId) {
Drawable drawable = ContextCompat.getDrawable(getContext(), drawableId);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} else {
throw new IllegalArgumentException("unsupported drawable type");
}
}
}