android 視訊錄製進度條(分段錄製,回滾刪除,類似美拍錄製)
阿新 • • 發佈:2019-01-22
最近因為公司啟動微視訊專案,負責視訊錄製及視訊編輯這塊工作,而首先視訊錄製這塊需要支援分段錄製,和回滾刪除功能。
所以就做了這麼繼承View自定義了這個一個進度條小demo,有待完善及優化。
效果圖先出場
因為比較簡單加上有註釋,就不再多囉嗦,直接上程式碼了。
public class RecordProgressView extends View { // 最長錄製時間 和 最小錄製時間 public final static float MAX_RECORD_TIME = 30000f; public final static float MIN_RECORD_TIME = 5000f; // 各種畫筆 進度 游標 最小時間標線 分段分割線 回滾 private Paint progressPaint, flashPaint, minTimePaint, breakPaint, rollbackPaint; // 游標寬度 private float flashWidth = 10f; // 最小時間標線寬度 private float minTimeWidth = 5f; // 分段分割線寬度 private float breakWidth = 2f; // 背景及各種畫筆顏色 private int backgroundColor = Color.parseColor("#525252"); private int progressColor = Color.parseColor("#86b00b"); private int flashColor = Color.parseColor("#FFFFFF"); private int minTimeColor = Color.parseColor("#FF0000"); private int breakColor = Color.parseColor("#000000"); private int rollbackColor = Color.parseColor("#e93c50"); // 閃動游標是否可見 private boolean isFlashVisible = true; // 游標繪製時間戳 private long lastDrawFlashTime = 0; // 每次繪製完成後,進度條的長度 private float countWidth = 0; private float perWidth; // 錄製片段 private LinkedList<Integer> recordPartList = new LinkedList<>(); private volatile RecordState currentState = RecordState.PAUSE; public RecordProgressView(Context context) { super(context); init(); } public RecordProgressView(Context paramContext, AttributeSet paramAttributeSet) { super(paramContext, paramAttributeSet); init(); } public RecordProgressView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) { super(paramContext, paramAttributeSet, paramInt); init(); } private void init() { DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); int screenWidth = displayMetrics.widthPixels; perWidth = screenWidth / MAX_RECORD_TIME; progressPaint = new Paint(); flashPaint = new Paint(); minTimePaint = new Paint(); breakPaint = new Paint(); rollbackPaint = new Paint(); setBackgroundColor(backgroundColor); progressPaint.setColor(progressColor); flashPaint.setColor(flashColor); minTimePaint.setColor(minTimeColor); breakPaint.setColor(breakColor); rollbackPaint.setColor(rollbackColor); } /** * @description 更新錄製狀態 */ public void changeRecordState(RecordState state) { if (currentState == state) return; if (currentState != RecordState.START && state == RecordState.START && !recordPartList.isEmpty()) { recordPartList.add(recordPartList.getLast()); } currentState = state; if (state == RecordState.DELETE) { if ((recordPartList != null) && (!recordPartList.isEmpty())) { recordPartList.removeLast(); } } } public void resetProgress() { currentState = RecordState.PAUSE; recordPartList.clear(); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); // onDraw是此自定義View的核心了 int progressHeight = getMeasuredHeight(); long currentTimeMillis = System.currentTimeMillis(); countWidth = 0; // 繪製錄製片段和分割線 if (!recordPartList.isEmpty()) { long previousTime = 0; long currentTime = 0; for (Integer aTimeList : recordPartList) { currentTime = aTimeList; float left = countWidth; countWidth += (currentTime - previousTime) * perWidth; canvas.drawRect(left, 0, countWidth - breakWidth, progressHeight, progressPaint); canvas.drawRect(countWidth - breakWidth, 0, countWidth, progressHeight, breakPaint); previousTime = currentTime; } } // 繪製最小時間分割線 if (recordPartList.isEmpty() || (!recordPartList.isEmpty() && recordPartList.getLast() <= MIN_RECORD_TIME)) { float left = perWidth * MIN_RECORD_TIME; canvas.drawRect(left, 0, left + minTimeWidth, progressHeight, minTimePaint); } // 繪製回滾狀態 if (currentState == RecordState.ROLLBACK) { long lastPartStartTime = recordPartList.size() > 1 ? recordPartList.get(recordPartList.size() - 2) : 0; long lastPartEndTime = recordPartList.size() > 0 ? recordPartList.get(recordPartList.size() - 1) : 0; float left = countWidth - (lastPartEndTime - lastPartStartTime) * perWidth; float right = countWidth; canvas.drawRect(left, 0, right, progressHeight, rollbackPaint); } // 繪製錄製進度 if (currentState == RecordState.START) { canvas.drawRect(countWidth, 0, countWidth + flashWidth, getMeasuredHeight(), flashPaint); } else { // 如果當前不是錄製狀態的話 游標是閃動的 而閃動的時間是這裡800 if (lastDrawFlashTime == 0 || currentTimeMillis - lastDrawFlashTime >= 800) { isFlashVisible = !isFlashVisible; lastDrawFlashTime = System.currentTimeMillis(); } if (isFlashVisible) { canvas.drawRect(countWidth, 0, countWidth + flashWidth, getMeasuredHeight(), flashPaint); } } // 基於 Android 16毫秒 重新整理 getHandler().postDelayed(invalidateRunnable, 16); } private Runnable invalidateRunnable = new Runnable() { @Override public void run() { switch (currentState) { case START: // 更新繪製進度 if (recordPartList.size() > 0) recordPartList.add(recordPartList.removeLast() + 16); else recordPartList.add(16); break; } invalidate(); } }; public int getLastTime() { if ((recordPartList != null) && (!recordPartList.isEmpty())) { return recordPartList.getLast(); } return 0; } public int getLastStartTime() { try { if ((recordPartList != null) && (!recordPartList.isEmpty())) { return recordPartList.get(recordPartList.size() - 2); } } catch (Exception e) { e.printStackTrace(); } return 0; } public boolean isRecordEmpty() { return recordPartList.isEmpty(); } /** * @description 視訊錄製的各種狀態 */ public enum RecordState { START(0x1), PAUSE(0x2), ROLLBACK(0x3), DELETE(0x4); private int value; RecordState(int intValue) { value = intValue; } int getValue() { return value; } } }