Android实现步进式录像进度条
16lz
2021-01-26
现在的APP对用户的体验要求越来越高,操作简单、样式新颖的交互能够提高用户的黏性。今天来实现一下步进式录像进度条,秒拍中用到这样的进度条,如下图:
下面来简单实现一下:
activity_main.xml
[html] view plain copy
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context=".MainActivity" >
- <RelativeLayout
- android:id="@+id/progress_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
- <com.jackie.steppingprogressbar.SteppingProgressBar
- android:id="@+id/stepping_progressbar"
- android:layout_width="match_parent"
- android:layout_height="50dp" />
- RelativeLayout>
- <LinearLayout
- android:id="@+id/button_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/progress_layout"
- android:layout_marginTop="30dp" >
- <Button
- android:id="@+id/btn_start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="15dp"
- android:onClick="onStartClick"
- android:text="开始" />
- <Button
- android:id="@+id/btn_stop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:onClick="onStopClick"
- android:text="停止" />
- <Button
- android:id="@+id/btn_reset"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:onClick="onResetClick"
- android:text="重置" />
- <Button
- android:id="@+id/btn_delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:onClick="onDeleteClick"
- android:text="删除" />
- LinearLayout>
- RelativeLayout>
[java] view plain copy
- package com.jackie.steppingprogressbar;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Paint.Style;
- import android.graphics.Rect;
- import android.graphics.Typeface;
- import android.util.AttributeSet;
- import android.view.View;
- public class SteppingProgressBar extends View {
- private Paint mPaint;
- private int mMaxWidth;
- private float mPercent = 0;
- private boolean mIsProgressPause;
- private boolean mAddTimeStamp;
- private List
mTimeStampPosition = new ArrayList(); - private List
mTimeStampPercent = new ArrayList(); - private final int STATE_NORMAL = 1;
- private final int STATE_DELETE_PREPARE = 2;
- private final int STATE_DELETE_DONE = 3;
- private int mState = STATE_NORMAL;
- private int MAX_PERCENT = 100;
- private final static int PROGRESS_TEXT_SIZE = 56;
- private final static int PROGRESS_SCALE = 1000;
- private final static int PROGRESS_BACKGROUND_COLOR = Color.parseColor("#66030e18");
- private final static int PROGRESS_PASSED_COLOR = Color.parseColor("#7cb855");
- private final static int PROGRESS_STAMP_COLOR = Color.parseColor("#4a7b17");
- private final static int PROGRESS_TEXT_COLOR = Color.parseColor("#ff0000");
- private final static int PROGRESS_DELETING_COLOR = Color.parseColor("#3c6e57");
- private SteppingProgressBarCallbackListener mSteppingProgressBarCallbackListener = null;
- public void setOnDeleteCallbackListener(SteppingProgressBarCallbackListener listener) {
- this.mSteppingProgressBarCallbackListener = listener;
- }
- public interface SteppingProgressBarCallbackListener {
- /* 删除完成的回调 */
- public void deleteDone(float percent);
- }
- public SteppingProgressBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- initData();
- }
- private void initData() {
- mPaint = new Paint();
- mPaint.setAlpha(255);
- mPaint.setStyle(Style.FILL);
- mPaint.setDither(true); //防抖动
- mPaint.setAntiAlias(true); //放锯齿
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- //获取尺寸
- int size = MeasureSpec.getSize(heightMeasureSpec);
- size = (int)(size + PROGRESS_TEXT_SIZE + 10);
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- //绘制底色
- mPaint.setColor(PROGRESS_BACKGROUND_COLOR);
- float width = mMaxWidth = getWidth();
- float height = getHeight() - PROGRESS_TEXT_SIZE - 10;
- canvas.drawRect(0, 0, width, height, mPaint);
- //绘制进度色
- mPaint.setColor(PROGRESS_PASSED_COLOR);
- width = (float) mPercent / (float) MAX_PERCENT * width;
- canvas.drawRect(0, 0, width, height, mPaint);
- //在下次进度条重新开始时,计算上次的分隔条
- if (mAddTimeStamp && mState == STATE_NORMAL && !mIsProgressPause) {
- mAddTimeStamp = false;
- Rect mRect = new Rect();
- mRect.left = (int) (width - 4);
- mRect.top = 0;
- mRect.right = (int) width;
- mRect.bottom = (int) height;
- mTimeStampPosition.add(mRect);
- mTimeStampPercent.add(mPercent);
- }
- //绘制所有分隔条
- for (Rect mRect : mTimeStampPosition) {
- mPaint.setColor(PROGRESS_STAMP_COLOR);
- canvas.drawRect(mRect, mPaint);
- }
- //绘制进度值文本
- mPaint.setStrokeWidth(0);
- mPaint.setColor(PROGRESS_TEXT_COLOR);
- mPaint.setTextSize(PROGRESS_TEXT_SIZE);
- mPaint.setTypeface(Typeface.DEFAULT);
- float textWidth = mPaint.measureText(mPercent / PROGRESS_SCALE + "s");
- if (mPercent != 0) {
- if (width + textWidth > mMaxWidth) {
- canvas.drawText(mPercent / PROGRESS_SCALE + "s", (width - textWidth), height + PROGRESS_TEXT_SIZE, mPaint);
- } else {
- canvas.drawText(mPercent / PROGRESS_SCALE + "s", width, height + PROGRESS_TEXT_SIZE, mPaint);
- }
- }
- if (mState == STATE_DELETE_DONE) {
- mState = STATE_NORMAL;
- //当删除完成时,准备绘制本次分隔条,当percent为0的时候不绘制
- if (mPercent != 0) {
- this.mAddTimeStamp = true;
- }
- } else if (mState == STATE_DELETE_PREPARE) {
- //当准备删除时,将上段时间内的进度条变色
- mPaint.setColor(PROGRESS_DELETING_COLOR);
- int left;
- if (mTimeStampPosition != null && mTimeStampPosition.size() > 0) {
- left = mTimeStampPosition.get(mTimeStampPosition.size() -1).right;
- } else {
- left = 0;
- }
- canvas.drawRect(left, 0, width, height, mPaint);
- }
- }
- /**
- * 进度条的最大值
- * @param maxPercent
- */
- public void setMax(int maxPercent) {
- this.MAX_PERCENT = maxPercent;
- }
- /**
- * 当前进度
- * @return
- */
- public float getProgress() {
- return mPercent;
- }
- /**
- * 设置当前进度
- * @param percent
- */
- public void setProgress(float percent) {
- if (percent < 0) {
- return;
- }
- if (percent >= MAX_PERCENT) {
- percent = MAX_PERCENT;
- }
- this.mPercent = percent;
- this.mState = STATE_NORMAL;
- this.mIsProgressPause = false;
- invalidate();
- }
- /**
- * 设置视频录制中间的断点时间戳
- * @param timeStamp
- */
- public void setTimeStamp(boolean timeStamp) {
- this.mIsProgressPause = true;
- this.mAddTimeStamp = timeStamp;
- }
- /**
- * 准备删除前一段进度
- */
- public void deleteLastStepPrepare() {
- if (mState == STATE_DELETE_PREPARE) {
- return;
- }
- mState = STATE_DELETE_PREPARE;
- invalidate();
- }
- /**
- * 确认删除前一段进度
- */
- public void deleteLastStep() {
- if (mState != STATE_DELETE_PREPARE) {
- deleteLastStepPrepare();
- return;
- }
- if (mTimeStampPercent != null && mTimeStampPercent.size() > 0) {
- this.mPercent = mTimeStampPercent.remove(mTimeStampPercent.size() - 1);
- } else {
- this.mPercent = 0;
- }
- this.mAddTimeStamp = false;
- mState = STATE_DELETE_DONE;
- //操作断点
- if (mTimeStampPosition != null && mTimeStampPosition.size() > 0) {
- mTimeStampPosition.remove(mTimeStampPosition.size() - 1);
- }
- if (mSteppingProgressBarCallbackListener != null) {
- mSteppingProgressBarCallbackListener.deleteDone(this.mPercent);
- }
- invalidate();
- }
- /**
- * 取消删除前一段进度
- */
- public void deleteLastStepCancel() {
- if (mState == STATE_NORMAL) {
- return;
- }
- mState = STATE_DELETE_DONE;
- invalidate();
- }
- /**
- * 重置进度条
- */
- public void reset() {
- this.mPercent = 0;
- this.mAddTimeStamp = false;
- mTimeStampPosition.clear();
- mTimeStampPercent.clear();
- invalidate();
- }
- }
[java] view plain copy
- package com.jackie.steppingprogressbar;
- import com.jackie.steppingprogressbar.SteppingProgressBar.SteppingProgressBarCallbackListener;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.Menu;
- import android.view.View;
- public class MainActivity extends Activity {
- SteppingProgressBar mProgressBar;
- private boolean mIsStopped = true;
- private int mProgress;
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- setProgress();
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mProgressBar = (SteppingProgressBar) findViewById(R.id.stepping_progressbar);
- mProgressBar.setMax(10000);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- // getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
- public void onStartClick(View view) {
- if (!mIsStopped) {
- return;
- }
- mIsStopped = false;
- mHandler.removeMessages(0);
- mHandler.sendEmptyMessage(0);
- }
- private void setProgress() {
- if (mProgress > 10000) {
- mHandler.removeMessages(0);
- } else if (!mIsStopped) {
- mProgress += 100;
- mProgressBar.setProgress(mProgress);
- mHandler.sendEmptyMessageDelayed(0, 100);
- }
- }
- public void onStopClick(View view) {
- mIsStopped = true;
- mProgressBar.setTimeStamp(true);
- }
- public void onResetClick(View view) {
- mProgressBar.reset();
- mProgress = 0;
- }
- public void onDeleteClick(View view) {
- if (!mIsStopped) {
- return;
- }
- mProgressBar.deleteLastStep();
- mProgressBar.setOnDeleteCallbackListener(new SteppingProgressBarCallbackListener() {
- @Override
- public void deleteDone(float percent) {
- mProgress = (int) percent;
- }
- });
- }
- }
更多相关文章
- Android(安卓)应用界面绘制流程
- Surface与SurfaceHolder.Callback
- 【Android】毫无耦合性,一个Item根布局搞定 item侧滑删除菜单,像IO
- [置顶] Android项目的错误异常收集日志记录
- Android编程开发实现带进度条和百分比的多线程下载
- Android:自定义View实现随滑动由箭头变对勾的指示按钮
- android 画环形的资料
- android studio 2.x 升级到3.0之后 android device monitor 报错
- Android自定义view贝塞尔曲线