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


下面来简单实现一下:

activity_main.xml

[html]  view plain  copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingTop="@dimen/activity_vertical_margin"  
  7.     tools:context=".MainActivity" >  
  8.   
  9.     <RelativeLayout  
  10.         android:id="@+id/progress_layout"  
  11.         android:layout_width="match_parent"  
  12.         android:layout_height="wrap_content" >  
  13.   
  14.         <com.jackie.steppingprogressbar.SteppingProgressBar  
  15.             android:id="@+id/stepping_progressbar"  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="50dp" />  
  18.     RelativeLayout>  
  19.   
  20.     <LinearLayout  
  21.         android:id="@+id/button_layout"  
  22.         android:layout_width="match_parent"  
  23.         android:layout_height="wrap_content"  
  24.         android:layout_below="@id/progress_layout"  
  25.         android:layout_marginTop="30dp" >  
  26.   
  27.         <Button  
  28.             android:id="@+id/btn_start"  
  29.             android:layout_width="wrap_content"  
  30.             android:layout_height="wrap_content"  
  31.             android:layout_marginLeft="15dp"  
  32.             android:onClick="onStartClick"  
  33.             android:text="开始" />  
  34.   
  35.         <Button  
  36.             android:id="@+id/btn_stop"  
  37.             android:layout_width="wrap_content"  
  38.             android:layout_height="wrap_content"  
  39.             android:layout_marginLeft="10dp"  
  40.             android:onClick="onStopClick"  
  41.             android:text="停止" />  
  42.   
  43.         <Button  
  44.             android:id="@+id/btn_reset"  
  45.             android:layout_width="wrap_content"  
  46.             android:layout_height="wrap_content"  
  47.             android:layout_marginLeft="10dp"  
  48.             android:onClick="onResetClick"  
  49.             android:text="重置" />  
  50.   
  51.         <Button  
  52.             android:id="@+id/btn_delete"  
  53.             android:layout_width="wrap_content"  
  54.             android:layout_height="wrap_content"  
  55.             android:layout_marginLeft="10dp"  
  56.             android:onClick="onDeleteClick"  
  57.             android:text="删除" />  
  58.     LinearLayout>  
  59.   
  60. RelativeLayout>  
SteppingProgressBar.java

[java]  view plain  copy
  1. package com.jackie.steppingprogressbar;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.content.Context;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.Color;  
  9. import android.graphics.Paint;  
  10. import android.graphics.Paint.Style;  
  11. import android.graphics.Rect;  
  12. import android.graphics.Typeface;  
  13. import android.util.AttributeSet;  
  14. import android.view.View;  
  15.   
  16. public class SteppingProgressBar extends View {  
  17.     private Paint mPaint;  
  18.     private int mMaxWidth;  
  19.     private float mPercent = 0;  
  20.       
  21.     private boolean mIsProgressPause;  
  22.     private boolean mAddTimeStamp;  
  23.       
  24.     private List mTimeStampPosition = new ArrayList();  
  25.     private List mTimeStampPercent = new ArrayList();  
  26.   
  27.     private final int STATE_NORMAL = 1;  
  28.     private final int STATE_DELETE_PREPARE = 2;  
  29.     private final int STATE_DELETE_DONE = 3;  
  30.     private int mState = STATE_NORMAL;  
  31.       
  32.     private int MAX_PERCENT = 100;  
  33.     private final static int PROGRESS_TEXT_SIZE = 56;  
  34.     private final static int PROGRESS_SCALE = 1000;  
  35.     private final static int PROGRESS_BACKGROUND_COLOR = Color.parseColor("#66030e18");  
  36.     private final static int PROGRESS_PASSED_COLOR = Color.parseColor("#7cb855");  
  37.     private final static int PROGRESS_STAMP_COLOR = Color.parseColor("#4a7b17");  
  38.     private final static int PROGRESS_TEXT_COLOR = Color.parseColor("#ff0000");  
  39.     private final static int PROGRESS_DELETING_COLOR = Color.parseColor("#3c6e57");  
  40.       
  41.     private SteppingProgressBarCallbackListener mSteppingProgressBarCallbackListener = null;  
  42.       
  43.     public void setOnDeleteCallbackListener(SteppingProgressBarCallbackListener listener) {  
  44.         this.mSteppingProgressBarCallbackListener = listener;  
  45.     }  
  46.       
  47.     public interface SteppingProgressBarCallbackListener {  
  48.         /* 删除完成的回调 */  
  49.         public void deleteDone(float percent);  
  50.     }  
  51.       
  52.     public SteppingProgressBar(Context context, AttributeSet attrs) {  
  53.         super(context, attrs);  
  54.         initData();  
  55.     }  
  56.       
  57.     private void initData() {  
  58.         mPaint = new Paint();  
  59.           
  60.         mPaint.setAlpha(255);  
  61.         mPaint.setStyle(Style.FILL);  
  62.         mPaint.setDither(true);  //防抖动  
  63.         mPaint.setAntiAlias(true); //放锯齿  
  64.     }  
  65.       
  66.     @Override  
  67.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  68.         //获取尺寸  
  69.         int size = MeasureSpec.getSize(heightMeasureSpec);  
  70.         size = (int)(size + PROGRESS_TEXT_SIZE + 10);  
  71.         heightMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);  
  72.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  73.     }  
  74.       
  75.     @Override  
  76.     protected void onDraw(Canvas canvas) {  
  77.         super.onDraw(canvas);  
  78.           
  79.         //绘制底色  
  80.         mPaint.setColor(PROGRESS_BACKGROUND_COLOR);  
  81.         float width = mMaxWidth = getWidth();  
  82.         float height = getHeight() - PROGRESS_TEXT_SIZE - 10;  
  83.         canvas.drawRect(00, width, height, mPaint);  
  84.           
  85.         //绘制进度色  
  86.         mPaint.setColor(PROGRESS_PASSED_COLOR);  
  87.         width = (float) mPercent / (float) MAX_PERCENT * width;  
  88.         canvas.drawRect(00, width, height, mPaint);  
  89.           
  90.         //在下次进度条重新开始时,计算上次的分隔条  
  91.         if (mAddTimeStamp && mState == STATE_NORMAL && !mIsProgressPause) {  
  92.             mAddTimeStamp = false;  
  93.             Rect mRect = new Rect();  
  94.             mRect.left = (int) (width - 4);   
  95.             mRect.top = 0;  
  96.             mRect.right = (int) width;  
  97.             mRect.bottom = (int) height;  
  98.             mTimeStampPosition.add(mRect);  
  99.             mTimeStampPercent.add(mPercent);  
  100.         }  
  101.           
  102.         //绘制所有分隔条  
  103.         for (Rect mRect : mTimeStampPosition) {  
  104.             mPaint.setColor(PROGRESS_STAMP_COLOR);  
  105.             canvas.drawRect(mRect, mPaint);  
  106.         }  
  107.           
  108.         //绘制进度值文本  
  109.         mPaint.setStrokeWidth(0);  
  110.         mPaint.setColor(PROGRESS_TEXT_COLOR);  
  111.         mPaint.setTextSize(PROGRESS_TEXT_SIZE);  
  112.         mPaint.setTypeface(Typeface.DEFAULT);  
  113.         float textWidth = mPaint.measureText(mPercent / PROGRESS_SCALE + "s");  
  114.         if (mPercent != 0) {  
  115.             if (width + textWidth > mMaxWidth) {  
  116.                 canvas.drawText(mPercent / PROGRESS_SCALE + "s", (width - textWidth), height + PROGRESS_TEXT_SIZE, mPaint);  
  117.             } else {  
  118.                 canvas.drawText(mPercent / PROGRESS_SCALE + "s", width, height + PROGRESS_TEXT_SIZE, mPaint);  
  119.             }  
  120.         }  
  121.           
  122.         if (mState == STATE_DELETE_DONE) {  
  123.             mState = STATE_NORMAL;  
  124.             //当删除完成时,准备绘制本次分隔条,当percent为0的时候不绘制  
  125.             if (mPercent != 0) {  
  126.                 this.mAddTimeStamp = true;  
  127.             }  
  128.         } else if (mState == STATE_DELETE_PREPARE) {  
  129.             //当准备删除时,将上段时间内的进度条变色  
  130.             mPaint.setColor(PROGRESS_DELETING_COLOR);  
  131.             int left;  
  132.             if (mTimeStampPosition != null && mTimeStampPosition.size() > 0) {  
  133.                 left = mTimeStampPosition.get(mTimeStampPosition.size() -1).right;  
  134.             } else {  
  135.                 left = 0;  
  136.             }  
  137.               
  138.             canvas.drawRect(left, 0, width, height, mPaint);  
  139.         }  
  140.     }  
  141.       
  142.     /** 
  143.      * 进度条的最大值 
  144.      * @param maxPercent 
  145.      */  
  146.     public void setMax(int maxPercent) {  
  147.         this.MAX_PERCENT = maxPercent;  
  148.     }  
  149.       
  150.     /** 
  151.      * 当前进度 
  152.      * @return 
  153.      */  
  154.     public float getProgress() {  
  155.         return mPercent;  
  156.     }  
  157.       
  158.     /** 
  159.      * 设置当前进度 
  160.      * @param percent 
  161.      */  
  162.     public void setProgress(float percent) {  
  163.         if (percent < 0) {  
  164.             return;  
  165.         }  
  166.           
  167.         if (percent >= MAX_PERCENT) {  
  168.             percent = MAX_PERCENT;  
  169.         }  
  170.           
  171.         this.mPercent = percent;  
  172.         this.mState = STATE_NORMAL;  
  173.         this.mIsProgressPause = false;  
  174.           
  175.         invalidate();  
  176.     }  
  177.       
  178.     /** 
  179.      * 设置视频录制中间的断点时间戳 
  180.      * @param timeStamp 
  181.      */  
  182.     public void setTimeStamp(boolean timeStamp) {  
  183.         this.mIsProgressPause = true;  
  184.         this.mAddTimeStamp = timeStamp;  
  185.     }  
  186.       
  187.     /** 
  188.      * 准备删除前一段进度 
  189.      */  
  190.     public void deleteLastStepPrepare() {  
  191.         if (mState == STATE_DELETE_PREPARE) {  
  192.             return;  
  193.         }  
  194.           
  195.         mState = STATE_DELETE_PREPARE;  
  196.         invalidate();  
  197.     }  
  198.       
  199.     /** 
  200.      * 确认删除前一段进度 
  201.      */  
  202.     public void deleteLastStep() {  
  203.         if (mState != STATE_DELETE_PREPARE) {  
  204.             deleteLastStepPrepare();  
  205.             return;  
  206.         }  
  207.           
  208.         if (mTimeStampPercent != null && mTimeStampPercent.size() > 0) {  
  209.             this.mPercent = mTimeStampPercent.remove(mTimeStampPercent.size() - 1);  
  210.         } else {  
  211.             this.mPercent = 0;  
  212.         }  
  213.         this.mAddTimeStamp = false;  
  214.         mState = STATE_DELETE_DONE;  
  215.           
  216.         //操作断点  
  217.         if (mTimeStampPosition != null && mTimeStampPosition.size() > 0) {  
  218.             mTimeStampPosition.remove(mTimeStampPosition.size() - 1);  
  219.         }  
  220.               
  221.         if (mSteppingProgressBarCallbackListener != null) {  
  222.             mSteppingProgressBarCallbackListener.deleteDone(this.mPercent);  
  223.         }  
  224.               
  225.         invalidate();  
  226.     }  
  227.       
  228.     /** 
  229.      * 取消删除前一段进度 
  230.      */  
  231.     public void deleteLastStepCancel() {  
  232.         if (mState == STATE_NORMAL) {  
  233.             return;  
  234.         }  
  235.         mState = STATE_DELETE_DONE;  
  236.         invalidate();  
  237.     }  
  238.   
  239.     /** 
  240.      * 重置进度条 
  241.      */  
  242.     public void reset() {  
  243.         this.mPercent = 0;  
  244.         this.mAddTimeStamp = false;  
  245.         mTimeStampPosition.clear();  
  246.         mTimeStampPercent.clear();  
  247.   
  248.         invalidate();  
  249.     }  
  250. }  
MainActivity.java

[java]  view plain  copy
  1. package com.jackie.steppingprogressbar;  
  2.   
  3. import com.jackie.steppingprogressbar.SteppingProgressBar.SteppingProgressBarCallbackListener;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.os.Message;  
  9. import android.view.Menu;  
  10. import android.view.View;  
  11.   
  12. public class MainActivity extends Activity {  
  13.     SteppingProgressBar mProgressBar;  
  14.   
  15.     private boolean mIsStopped = true;  
  16.     private int mProgress;  
  17.   
  18.     private Handler mHandler = new Handler() {  
  19.   
  20.         @Override  
  21.         public void handleMessage(Message msg) {  
  22.             super.handleMessage(msg);  
  23.   
  24.             setProgress();  
  25.         }  
  26.     };  
  27.   
  28.     @Override  
  29.     protected void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.activity_main);  
  32.   
  33.         mProgressBar = (SteppingProgressBar) findViewById(R.id.stepping_progressbar);  
  34.         mProgressBar.setMax(10000);  
  35.     }  
  36.   
  37.     @Override  
  38.     public boolean onCreateOptionsMenu(Menu menu) {  
  39.         // Inflate the menu; this adds items to the action bar if it is present.  
  40.         // getMenuInflater().inflate(R.menu.main, menu);  
  41.         return true;  
  42.     }  
  43.   
  44.     public void onStartClick(View view) {  
  45.         if (!mIsStopped) {  
  46.             return;  
  47.         }  
  48.   
  49.         mIsStopped = false;  
  50.         mHandler.removeMessages(0);  
  51.         mHandler.sendEmptyMessage(0);  
  52.     }  
  53.   
  54.     private void setProgress() {  
  55.         if (mProgress > 10000) {  
  56.             mHandler.removeMessages(0);  
  57.         } else if (!mIsStopped) {  
  58.             mProgress += 100;  
  59.             mProgressBar.setProgress(mProgress);  
  60.             mHandler.sendEmptyMessageDelayed(0100);  
  61.         }  
  62.     }  
  63.   
  64.     public void onStopClick(View view) {  
  65.         mIsStopped = true;  
  66.         mProgressBar.setTimeStamp(true);  
  67.     }  
  68.   
  69.     public void onResetClick(View view) {  
  70.         mProgressBar.reset();  
  71.         mProgress = 0;  
  72.     }  
  73.   
  74.     public void onDeleteClick(View view) {  
  75.         if (!mIsStopped) {  
  76.             return;  
  77.         }  
  78.   
  79.         mProgressBar.deleteLastStep();  
  80.         mProgressBar.setOnDeleteCallbackListener(new SteppingProgressBarCallbackListener() {  
  81.               
  82.             @Override  
  83.             public void deleteDone(float percent) {  
  84.                 mProgress = (int) percent;  
  85.             }  
  86.         });  
  87.     }  
  88. }  
效果图如下:

   

更多相关文章

  1. Android(安卓)应用界面绘制流程
  2. Surface与SurfaceHolder.Callback
  3. 【Android】毫无耦合性,一个Item根布局搞定 item侧滑删除菜单,像IO
  4. [置顶] Android项目的错误异常收集日志记录
  5. Android编程开发实现带进度条和百分比的多线程下载
  6. Android:自定义View实现随滑动由箭头变对勾的指示按钮
  7. android 画环形的资料
  8. android studio 2.x 升级到3.0之后 android device monitor 报错
  9. Android自定义view贝塞尔曲线

随机推荐

  1. Android添加USB add-on硬件访问服务
  2. android 获取位置
  3. Android(安卓)Studio之编译t提示Invoke-c
  4. 学习目录
  5. ubuntu10.10下编译android内核源码
  6. android客户端程序访问服务器端webservic
  7. Android(安卓)Studio 1.5 opencv开发
  8. First day of android study
  9. Android(安卓)View和ViewGroup的关系
  10. Android构建工具Gradle知识1