一个炫酷的录制音视频控件

214 阅读2分钟

前言

前段时间说想静下心来学习一下有关音视频的知识,于是第一个需求就来了,需要做一个炫酷的录制音视频的控件。所以呢我就随手写了一个,
顺便复习了一下Android自定义view的相关知识。

效果图

废话不多说,先上一个效果图:

怎么样,效果是不是还可以?

代码分析

首先看一下这个view运动的整个过程,你会发现有四个状态:

private static final int STATUS_IDLE = 0x01;
private static final int STATUS_TRANSITION_RECORD = 0x02;
private static final int STATUS_RECORDING = 0x03;
private static final int STATUS_TRANSITION_IDLE = 0x04;

STATUS_IDLE:闲置状态,即啥也不干
STATUS_TRANSITION_RECORD:由闲置状态转为拍摄状态,即手指刚刚按下,实心圈变成空心圈的过程
STATUS_RECORDING:拍摄状态,即手指按下并且可以随意移动,空心圈闪烁的过程
STATUS_TRANSITION_IDLE:由拍摄转为闲置状态,即松开手指,空心圈再次变实心圈的过程

初始化操作:
private void init() {
    mCenterMaxRadius = UIUtils.dip2px(getContext(), 55); // 最大半径
    mCenterMinRadius = UIUtils.dip2px(getContext(), 40); // 最小半径
    mOriginRadius = UIUtils.dip2px(getContext(), 40); // 原始半径
    mStatus = STATUS_IDLE;
    mRadius = UIUtils.dip2px(getContext(), DEFAULT_RADIUS); // 默认半径
    mPaint = new Paint();
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setAntiAlias(true);
}

绘制过程:
@Override
protected void dispatchDraw(Canvas canvas) {
    canvas.save();
    canvas.translate(mTranslationX, mTranslationY);

    long now = SystemClock.uptimeMillis();
    // 当手指按下的时间长度超过阈值,触发状态改变
    if (mStatus == STATUS_TRANSITION_RECORD && now - mStatusChangeTime > TRANSITION_DURATION) {
        changeStatusTo(STATUS_RECORDING);
    }

    if (mStatus == STATUS_TRANSITION_IDLE) {
        if (now - mStatusChangeTime > TRANSITION_DURATION) {
            changeStatusTo(STATUS_IDLE);
            mTranslationX = 0;
            mTranslationY = 0;
            invalidate();
        } else {
            mTranslationX = (1 - 1.0f * (now - mStatusChangeTime) / TRANSITION_DURATION) * mTranslationX;
            mTranslationY = (1 - 1.0f * (now - mStatusChangeTime) / TRANSITION_DURATION) * mTranslationY;
        }
    }
    // 绘制空心圈
    drawBorder(canvas);
    canvas.restore();
    if (mStatus != STATUS_IDLE) {
        invalidate();
    }
}

onTouch事件处理:
@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mDownX = event.getX();
            mDownY = event.getY();
            changeStatusTo(STATUS_TRANSITION_RECORD);
            if (mRecordListener != null) {
                mRecordListener.onRecordStart();
            }
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            mTranslationX = event.getX() - mDownX;
            mTranslationY = event.getY() - mDownY;
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (mRecordListener != null) {
                mRecordListener.onRecordEnd();
            }
            changeStatusTo(STATUS_TRANSITION_IDLE);
            break;
    }
    return true;
}

这个自定义view是集成FrameLayout的,很多同学很奇怪为什么不是复写onDraw()方法,而是复写 dispatchDraw()方法,具体愿意请参考 为什么自定义ViewGroup ondraw方法不会被调用

End

附:源码地址

如果有问题,请大神们多多指正。