Android实现步进式录像进度条

现在的APP对用户的体验要求越来越高,操作简单、样式新颖的交互能够提高用户的黏性。今天来实现一下步进式录像进度条,秒拍中用到这样的进度条,如下图:


下面来简单实现一下:

activity_main.xml

<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>
SteppingProgressBar.java

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<Rect> mTimeStampPosition = new ArrayList<Rect>();
	private List<Float> mTimeStampPercent = new ArrayList<Float>();

	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();
	}
}
MainActivity.java

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;
			}
		});
	}
}
效果图如下:

   


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值