Android 微信小视频录制功能
开发之前
这几天接触了一下和视频相关的控件, 所以, 继之前的微信摇一摇, 我想到了来实现一下微信小视频录制的功能, 它的功能点比较多, 我每天都抽出点时间来写写, 说实话, 有些东西还是比较费劲, 希望大家认真看看, 说得不对的地方还请大家在评论中指正. 废话不多说, 进入正题.
开发环境
最近刚更新的, 没更新的小伙伴们抓紧了
Android Studio 2.2.2
JDK1.7
API 24
Gradle 2.2.2
相关知识点
视频录制界面 SurfaceView 的使用
Camera的使用
相机的对焦, 变焦
视频录制控件MediaRecorder的使用
简单自定义View
GestureDetector(手势检测)的使用
用到的东西真不少, 不过别着急, 咱们一个一个来.
开始开发
案例分析
大家可以打开自己微信里面的小视频, 一块简单的分析一下它的功能点有哪些 ?
基本的视频预览功能
长按 “按住拍” 实现视频的录制
录制过程中的进度条从两侧向中间变短
当松手或者进度条走到尽头视频停止录制 并保存
从 “按住拍” 上滑取消视频的录制
双击屏幕 变焦 放大
根据上述的分析, 我们一步一步的完成
搭建布局
布局界面的实现还可以, 难度不大
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/main_tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="150dp"
android:elevation="1dp"
android:text="双击放大"
android:textColor="#FFFFFF"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SurfaceView
android:id="@+id/main_surface_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorApp"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/main_press_control"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.lulu.weichatsamplevideo.BothWayProgressBar
android:id="@+id/main_progress_bar"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="按住拍"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textColor="#00ff00"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>视频预览的实现
step1: 得到SufaceView控件, 设置基本属性和相应监听(该控件的创建是异步的, 只有在真正”准备”好之后才能调用)
mSurfaceView = (SurfaceView) findViewById(R.id.main_surface_view); //设置屏幕分辨率 mSurfaceHolder.setFixedSize(videoWidth, videoHeight); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mSurfaceHolder.addCallback(this);
step2: 实现接口的方法, surfaceCreated方法中开启视频的预览, 在surfaceDestroyed中销毁
//////////////////////////////////////////////
// SurfaceView回调
/////////////////////////////////////////////
@Override
public void surfaceCreated(SurfaceHolder holder) {
mSurfaceHolder = holder;
startPreView(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
Log.d(TAG, "surfaceDestroyed: ");
//停止预览并释放摄像头资源
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if (mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder = null;
}
}step3: 实现视频预览的方法
/**
* 开启预览
*
* @param holder
*/
private void startPreView(SurfaceHolder holder) {
Log.d(TAG, "startPreView: ");
if (mCamera == null) {
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
}
if (mMediaRecorder == null) {
mMediaRecorder = new MediaRecorder();
}
if (mCamera != null) {
mCamera.setDisplayOrientation(90);
try {
mCamera.setPreviewDisplay(holder);
Camera.Parameters parameters = mCamera.getParameters();
//实现Camera自动对焦
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes != null) {
for (String mode : focusModes) {
mode.contains("continuous-video");
parameters.setFocusMode("continuous-video");
}
}
mCamera.setParameters(parameters);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}Note: 上面添加了自动对焦的代码, 但是部分手机可能不支持
自定义双向缩减的进度条
有些像我一样的初学者一看到自定义某某View, 就觉得比较牛X. 其实呢, Google已经替我们写好了很多代码, 所以我们用就行了.而且咱们的这个进度条也没啥, 不就是一根线, 今天咱就来说说.
step1: 继承View, 完成初始化
private static final String TAG = "BothWayProgressBar";
//取消状态为红色bar, 反之为绿色bar
private boolean isCancel = false;
private Context mContext;
//正在录制的画笔
private Paint mRecordPaint;
//上滑取消时的画笔
private Paint mCancelPaint;
//是否显示
private int mVisibility;
// 当前进度
private int progress;
//进度条结束的监听
private OnProgressEndListener mOnProgressEndListener;
public BothWayProgressBar(Context context) {
super(context, null);
}
public BothWayProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
private void init() {
mVisibility = INVISIBLE;
mRecordPaint = new Paint();
mRecordPaint.setColor(Color.GREEN);
mCancelPaint = new Paint();
mCancelPaint.setColor(Color.RED);
}Note: OnProgressEndListener, 主要用于当进度条走到中间了, 好通知相机停止录制, 接口如下:
public interface OnProgressEndListener{
void onProgressEndListener();
}
/**
* 当进度条结束后的 监听
* @param onProgressEndListener
*/
public void setOnProgressEndListener(OnProgressEndListener onProgressEndListener) {
mOnProgressEndListener = onProgressEndListener;
}step2 :设置Setter方法用于通知我们的Progress改变状态
/** * 设置进度 * @p

