zoukankan      html  css  js  c++  java
  • Android 数字进度条NumberProgressBar

     

    转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0813/1645.html

    原生的ProgressBar在不同的主题下风格迥异,有矩形条状的,有代表加载进行中的圆圈风格的,在4.0的holo风格下这些ProgressBar都还比较好看,但是在非holo风格下让人厌烦。我不排斥使用原生控件,但是有时我们的app可能比较个性化,需要更有个性的ProgressBar。

    下面这款开源ProgressBar就比较有个性。

    NumberProgressBar

    github地址 https://github.com/daimajia/NumberProgressBar

    该控件虽然也叫ProgressBar,但是和sdk中的ProgressBar控件没有任何继承关系,直接继承子view。控件分为三部分,如图:

    用法:

    xml中

    1.  
      <com.daimajia.numberprogressbar.NumberProgressBar
    2.  
      android:id="@+id/number_progress_bar"
    3.  
      style="@style/NumberProgressBar_Default" />
    除了默认的style,你还可以设置成如下style:

    NumberProgressBar_Default 

    NumberProgressBar_Passing_Green 

    NumberProgressBar_Relax_Blue 

    NumberProgressBar_Grace_Yellow 

    NumberProgressBar_Warning_Red 

    NumberProgressBar_Funny_Orange 

    NumberProgressBar_Beauty_Red 

    NumberProgressBar_Twinkle_Night

    对应的外观如下:

    除了直接用已经定义好的style,你还可以通过设置属性来改变外观。

    NumberProgressBar的一些属性:

    reached area和unreached area

    • 颜色

    • 高度

    文字部分,描述进程的百分比数字

    • 颜色

    • 字体大小

    • 是否可见

    • 和reached area与unreached area之间的距离

    整个bar

    • 最大进度 max progress

    • 当前进度 current progress

    比如默认情况下

    1.  
      <com.daimajia.numberprogressbar.NumberProgressBar
    2.  
      android:layout_width="wrap_content"
    3.  
      android:layout_height="wrap_content"
    4.  
      custom:progress_unreached_color="#CCCCCC"
    5.  
      custom:progress_reached_color="#3498DB"
    6.  
      custom:progress_unreached_bar_height="0.75dp"
    7.  
      custom:progress_reached_bar_height="1.5dp"
    8.  
      custom:progress_text_size="10sp"
    9.  
      custom:progress_text_color="#3498DB"
    10.  
      custom:progress_text_offset="1dp"
    11.  
      custom:progress_text_visibility="visible"
    12.  
      custom:max="100"
    13.  
      custom:progress="80" />
    能体现进度的动画效果:

    如上面的第一张图所示,github项目中的demo实现了NumberProgressBar的动画效果,但是这个动画效果并不是NumberProgressBar自带的,而是在外部通过不断调用setProgress做到的,demo中

    1.  
      final NumberProgressBar bnp = (NumberProgressBar)findViewById(R.id.numberbar1);
    2.  
      counter = 0;
    3.  
      timer = new Timer();
    4.  
      timer.schedule(new TimerTask() {
    5.  
      @Override
    6.  
      public void run() {
    7.  
      runOnUiThread(new Runnable() {
    8.  
      @Override
    9.  
      public void run() {
    10.  
      bnp.incrementProgressBy(1);
    11.  
      counter ++;
    12.  
      if (counter == 110) {
    13.  
      bnp.setProgress(0);
    14.  
      counter=0;
    15.  
      }
    16.  
      }
    17.  
      });
    18.  
      }
    19.  
      }, 1000, 100);
    incrementProgressBy表示Progress在现有基础上增加多少,从上面的代码可以看出,demo中 NumberProgressBar 的动态增加是采用timer实现的,也可以用属性动画来实现,当然在现实运用中可能是一些跟网络有关的事件来实现。

    NumberProgressBar的源码实现:

    如果你已经学会了如何自定义一个view,那么NumberProgressBar的代码是很容易看懂的。这里想指出的是有个细节我个人持保留意见,那就是作者在onMeasure方法中调用了自己实现的measure方法,在View的绘制中是先measure然后再在measure方法中调用onMeasure,而继承子view的子类一般只重写onMeasure方法。虽然这里并不会引起什么错误,但是我觉得还是遵守view的绘制流程比较好。

    最后贴出NumberProgressBar的java部分的代码,代码不多:

    1.  
      package com.daimajia.numberprogressbar;
    2.  
      import android.content.Context;
    3.  
      import android.content.res.TypedArray;
    4.  
      import android.graphics.Canvas;
    5.  
      import android.graphics.Color;
    6.  
      import android.graphics.Paint;
    7.  
      import android.graphics.RectF;
    8.  
      import android.os.Bundle;
    9.  
      import android.os.Parcelable;
    10.  
      import android.util.AttributeSet;
    11.  
      import android.view.View;
    12.  
      /**
    13.  
      * Created by daimajia on 14-4-30.
    14.  
      */
    15.  
      public class NumberProgressBar extends View {
    16.  
      private Context mContext;
    17.  
      /**
    18.  
      * The max progress, default is 100
    19.  
      */
    20.  
      private int mMax = 100;
    21.  
      /**
    22.  
      * current progress, can not exceed the max progress.
    23.  
      */
    24.  
      private int mProgress = 0;
    25.  
      /**
    26.  
      * the progress area bar color
    27.  
      */
    28.  
      private int mReachedBarColor;
    29.  
      /**
    30.  
      * the bar unreached area color.
    31.  
      */
    32.  
      private int mUnreachedBarColor;
    33.  
      /**
    34.  
      * the progress text color.
    35.  
      */
    36.  
      private int mTextColor;
    37.  
      /**
    38.  
      * the progress text size
    39.  
      */
    40.  
      private float mTextSize;
    41.  
      /**
    42.  
      * the height of the reached area
    43.  
      */
    44.  
      private float mReachedBarHeight;
    45.  
      /**
    46.  
      * the height of the unreached area
    47.  
      */
    48.  
      private float mUnreachedBarHeight;
    49.  
      private final int default_text_color = Color.rgb(66, 145, 241);
    50.  
      private final int default_reached_color = Color.rgb(66,145,241);
    51.  
      private final int default_unreached_color = Color.rgb(204, 204, 204);
    52.  
      private final float default_progress_text_offset;
    53.  
      private final float default_text_size;
    54.  
      private final float default_reached_bar_height;
    55.  
      private final float default_unreached_bar_height;
    56.  
      /**
    57.  
      * for save and restore instance of progressbar.
    58.  
      */
    59.  
      private static final String INSTANCE_STATE = "saved_instance";
    60.  
      private static final String INSTANCE_TEXT_COLOR = "text_color";
    61.  
      private static final String INSTANCE_TEXT_SIZE = "text_size";
    62.  
      private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height";
    63.  
      private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color";
    64.  
      private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height";
    65.  
      private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color";
    66.  
      private static final String INSTANCE_MAX = "max";
    67.  
      private static final String INSTANCE_PROGRESS = "progress";
    68.  
      private static final int PROGRESS_TEXT_VISIBLE = 0;
    69.  
      private static final int PROGRESS_TEXT_INVISIBLE = 1;
    70.  
      /**
    71.  
      * the width of the text that to be drawn
    72.  
      */
    73.  
      private float mDrawTextWidth;
    74.  
      /**
    75.  
      * the drawn text start
    76.  
      */
    77.  
      private float mDrawTextStart;
    78.  
      /**
    79.  
      *the drawn text end
    80.  
      */
    81.  
      private float mDrawTextEnd;
    82.  
      /**
    83.  
      * the text that to be drawn in onDraw()
    84.  
      */
    85.  
      private String mCurrentDrawText;
    86.  
      /**
    87.  
      * the Paint of the reached area.
    88.  
      */
    89.  
      private Paint mReachedBarPaint;
    90.  
      /**
    91.  
      * the Painter of the unreached area.
    92.  
      */
    93.  
      private Paint mUnreachedBarPaint;
    94.  
      /**
    95.  
      * the Painter of the progress text.
    96.  
      */
    97.  
      private Paint mTextPaint;
    98.  
      /**
    99.  
      * Unreached Bar area to draw rect.
    100.  
      */
    101.  
      private RectF mUnreachedRectF = new RectF(0,0,0,0);
    102.  
      /**
    103.  
      * reached bar area rect.
    104.  
      */
    105.  
      private RectF mReachedRectF = new RectF(0,0,0,0);
    106.  
      /**
    107.  
      * the progress text offset.
    108.  
      */
    109.  
      private float mOffset;
    110.  
      /**
    111.  
      * determine if need to draw unreached area
    112.  
      */
    113.  
      private boolean mDrawUnreachedBar = true;
    114.  
      private boolean mDrawReachedBar = true;
    115.  
      private boolean mIfDrawText = true;
    116.  
      public enum ProgressTextVisibility{
    117.  
      Visible,Invisible
    118.  
      };
    119.  
      public NumberProgressBar(Context context) {
    120.  
      this(context, null);
    121.  
      }
    122.  
      public NumberProgressBar(Context context, AttributeSet attrs) {
    123.  
      this(context, attrs, R.attr.numberProgressBarStyle);
    124.  
      }
    125.  
      public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    126.  
      super(context, attrs, defStyleAttr);
    127.  
      mContext = context;
    128.  
      default_reached_bar_height = dp2px(1.5f);
    129.  
      default_unreached_bar_height = dp2px(1.0f);
    130.  
      default_text_size = sp2px(10);
    131.  
      default_progress_text_offset = dp2px(3.0f);
    132.  
      //load styled attributes.
    133.  
      final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar,
    134.  
      defStyleAttr, 0);
    135.  
      mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color);
    136.  
      mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color,default_unreached_color);
    137.  
      mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color,default_text_color);
    138.  
      mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size);
    139.  
      mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height,default_reached_bar_height);
    140.  
      mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height,default_unreached_bar_height);
    141.  
      mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset,default_progress_text_offset);
    142.  
      int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility,PROGRESS_TEXT_VISIBLE);
    143.  
      if(textVisible != PROGRESS_TEXT_VISIBLE){
    144.  
      mIfDrawText = false;
    145.  
      }
    146.  
      setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress,0));
    147.  
      setMax(attributes.getInt(R.styleable.NumberProgressBar_max, 100));
    148.  
      //
    149.  
      attributes.recycle();
    150.  
      initializePainters();
    151.  
      }
    152.  
      @Override
    153.  
      protected int getSuggestedMinimumWidth() {
    154.  
      return (int)mTextSize;
    155.  
      }
    156.  
      @Override
    157.  
      protected int getSuggestedMinimumHeight() {
    158.  
      return Math.max((int)mTextSize,Math.max((int)mReachedBarHeight,(int)mUnreachedBarHeight));
    159.  
      }
    160.  
      @Override
    161.  
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    162.  
      setMeasuredDimension(measure(widthMeasureSpec,true), measure(heightMeasureSpec,false));
    163.  
      }
    164.  
      private int measure(int measureSpec,boolean isWidth){
    165.  
      int result;
    166.  
      int mode = MeasureSpec.getMode(measureSpec);
    167.  
      int size = MeasureSpec.getSize(measureSpec);
    168.  
      int padding = isWidth?getPaddingLeft()+getPaddingRight():getPaddingTop()+getPaddingBottom();
    169.  
      if(mode == MeasureSpec.EXACTLY){
    170.  
      result = size;
    171.  
      }else{
    172.  
      result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
    173.  
      result += padding;
    174.  
      if(mode == MeasureSpec.AT_MOST){
    175.  
      if(isWidth) {
    176.  
      result = Math.max(result, size);
    177.  
      }
    178.  
      else{
    179.  
      result = Math.min(result, size);
    180.  
      }
    181.  
      }
    182.  
      }
    183.  
      return result;
    184.  
      }
    185.  
      @Override
    186.  
      protected void onDraw(Canvas canvas) {
    187.  
      if(mIfDrawText){
    188.  
      calculateDrawRectF();
    189.  
      }else{
    190.  
      calculateDrawRectFWithoutProgressText();
    191.  
      }
    192.  
      if(mDrawReachedBar){
    193.  
      canvas.drawRect(mReachedRectF,mReachedBarPaint);
    194.  
      }
    195.  
      if(mDrawUnreachedBar) {
    196.  
      canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint);
    197.  
      }
    198.  
      if(mIfDrawText)
    199.  
      canvas.drawText(mCurrentDrawText,mDrawTextStart,mDrawTextEnd,mTextPaint);
    200.  
      }
    201.  
      private void initializePainters(){
    202.  
      mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    203.  
      mReachedBarPaint.setColor(mReachedBarColor);
    204.  
      mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    205.  
      mUnreachedBarPaint.setColor(mUnreachedBarColor);
    206.  
      mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    207.  
      mTextPaint.setColor(mTextColor);
    208.  
      mTextPaint.setTextSize(mTextSize);
    209.  
      }
    210.  
      private void calculateDrawRectFWithoutProgressText(){
    211.  
      mReachedRectF.left = getPaddingLeft();
    212.  
      mReachedRectF.top = getHeight()/2.0f - mReachedBarHeight / 2.0f;
    213.  
      mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight() )/(getMax()*1.0f) * getProgress() + getPaddingLeft();
    214.  
      mReachedRectF.bottom = getHeight()/2.0f + mReachedBarHeight / 2.0f;
    215.  
      mUnreachedRectF.left = mReachedRectF.right;
    216.  
      mUnreachedRectF.right = getWidth() - getPaddingRight();
    217.  
      mUnreachedRectF.top = getHeight()/2.0f + - mUnreachedBarHeight / 2.0f;
    218.  
      mUnreachedRectF.bottom = getHeight()/2.0f + mUnreachedBarHeight / 2.0f;
    219.  
      }
    220.  
      private void calculateDrawRectF(){
    221.  
      mCurrentDrawText = String.format("%d%%",getProgress()*100/getMax());
    222.  
      mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText);
    223.  
      if(getProgress() == 0){
    224.  
      mDrawReachedBar = false;
    225.  
      mDrawTextStart = getPaddingLeft();
    226.  
      }else{
    227.  
      mDrawReachedBar = true;
    228.  
      mReachedRectF.left = getPaddingLeft();
    229.  
      mReachedRectF.top = getHeight()/2.0f - mReachedBarHeight / 2.0f;
    230.  
      mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight() )/(getMax()*1.0f) * getProgress() - mOffset + getPaddingLeft();
    231.  
      mReachedRectF.bottom = getHeight()/2.0f + mReachedBarHeight / 2.0f;
    232.  
      mDrawTextStart = (mReachedRectF.right + mOffset);
    233.  
      }
    234.  
      mDrawTextEnd = (int) ((getHeight() / 2.0f) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f)) ;
    235.  
      if((mDrawTextStart + mDrawTextWidth )>= getWidth() - getPaddingRight()){
    236.  
      mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth;
    237.  
      mReachedRectF.right = mDrawTextStart - mOffset;
    238.  
      }
    239.  
      float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset;
    240.  
      if(unreachedBarStart >= getWidth() - getPaddingRight()){
    241.  
      mDrawUnreachedBar = false;
    242.  
      }else{
    243.  
      mDrawUnreachedBar = true;
    244.  
      mUnreachedRectF.left = unreachedBarStart;
    245.  
      mUnreachedRectF.right = getWidth() - getPaddingRight();
    246.  
      mUnreachedRectF.top = getHeight()/2.0f + - mUnreachedBarHeight / 2.0f;
    247.  
      mUnreachedRectF.bottom = getHeight()/2.0f + mUnreachedBarHeight / 2.0f;
    248.  
      }
    249.  
      }
    250.  
      /**
    251.  
      * get progress text color
    252.  
      * @return progress text color
    253.  
      */
    254.  
      public int getTextColor() {
    255.  
      return mTextColor;
    256.  
      }
    257.  
      /**
    258.  
      * get progress text size
    259.  
      * @return progress text size
    260.  
      */
    261.  
      public float getProgressTextSize() {
    262.  
      return mTextSize;
    263.  
      }
    264.  
      public int getUnreachedBarColor() {
    265.  
      return mUnreachedBarColor;
    266.  
      }
    267.  
      public int getReachedBarColor() {
    268.  
      return mReachedBarColor;
    269.  
      }
    270.  
      public int getProgress() {
    271.  
      return mProgress;
    272.  
      }
    273.  
      public int getMax() {
    274.  
      return mMax;
    275.  
      }
    276.  
      public float getReachedBarHeight(){
    277.  
      return mReachedBarHeight;
    278.  
      }
    279.  
      public float getUnreachedBarHeight(){
    280.  
      return mUnreachedBarHeight;
    281.  
      }
    282.  
      public void setProgressTextSize(float TextSize) {
    283.  
      this.mTextSize = TextSize;
    284.  
      mTextPaint.setTextSize(mTextSize);
    285.  
      invalidate();
    286.  
      }
    287.  
      public void setProgressTextColor(int TextColor) {
    288.  
      this.mTextColor = TextColor;
    289.  
      mTextPaint.setColor(mTextColor);
    290.  
      invalidate();
    291.  
      }
    292.  
      public void setUnreachedBarColor(int BarColor) {
    293.  
      this.mUnreachedBarColor = BarColor;
    294.  
      mUnreachedBarPaint.setColor(mReachedBarColor);
    295.  
      invalidate();
    296.  
      }
    297.  
      public void setReachedBarColor(int ProgressColor) {
    298.  
      this.mReachedBarColor = ProgressColor;
    299.  
      mReachedBarPaint.setColor(mReachedBarColor);
    300.  
      invalidate();
    301.  
      }
    302.  
      public void setMax(int Max) {
    303.  
      if(Max > 0){
    304.  
      this.mMax = Max;
    305.  
      invalidate();
    306.  
      }
    307.  
      }
    308.  
      public void incrementProgressBy(int by){
    309.  
      if(by > 0){
    310.  
      setProgress(getProgress() + by);
    311.  
      }
    312.  
      }
    313.  
      public void setProgress(int Progress) {
    314.  
      if(Progress <= getMax() && Progress >= 0){
    315.  
      this.mProgress = Progress;
    316.  
      invalidate();
    317.  
      }
    318.  
      }
    319.  
      @Override
    320.  
      protected Parcelable onSaveInstanceState() {
    321.  
      final Bundle bundle = new Bundle();
    322.  
      bundle.putParcelable(INSTANCE_STATE,super.onSaveInstanceState());
    323.  
      bundle.putInt(INSTANCE_TEXT_COLOR,getTextColor());
    324.  
      bundle.putFloat(INSTANCE_TEXT_SIZE, getProgressTextSize());
    325.  
      bundle.putFloat(INSTANCE_REACHED_BAR_HEIGHT,getReachedBarHeight());
    326.  
      bundle.putFloat(INSTANCE_UNREACHED_BAR_HEIGHT,getUnreachedBarHeight());
    327.  
      bundle.putInt(INSTANCE_REACHED_BAR_COLOR,getReachedBarColor());
    328.  
      bundle.putInt(INSTANCE_UNREACHED_BAR_COLOR,getUnreachedBarColor());
    329.  
      bundle.putInt(INSTANCE_MAX,getMax());
    330.  
      bundle.putInt(INSTANCE_PROGRESS,getProgress());
    331.  
      return bundle;
    332.  
      }
    333.  
      @Override
    334.  
      protected void onRestoreInstanceState(Parcelable state) {
    335.  
      if(state instanceof Bundle){
    336.  
      final Bundle bundle = (Bundle)state;
    337.  
      mTextColor = bundle.getInt(INSTANCE_TEXT_COLOR);
    338.  
      mTextSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
    339.  
      mReachedBarHeight = bundle.getFloat(INSTANCE_REACHED_BAR_HEIGHT);
    340.  
      mUnreachedBarHeight = bundle.getFloat(INSTANCE_UNREACHED_BAR_HEIGHT);
    341.  
      mReachedBarColor = bundle.getInt(INSTANCE_REACHED_BAR_COLOR);
    342.  
      mUnreachedBarColor = bundle.getInt(INSTANCE_UNREACHED_BAR_COLOR);
    343.  
      initializePainters();
    344.  
      setMax(bundle.getInt(INSTANCE_MAX));
    345.  
      setProgress(bundle.getInt(INSTANCE_PROGRESS));
    346.  
      super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
    347.  
      return;
    348.  
      }
    349.  
      super.onRestoreInstanceState(state);
    350.  
      }
    351.  
      public float dp2px(float dp) {
    352.  
      final float scale = getResources().getDisplayMetrics().density;
    353.  
      return dp * scale + 0.5f;
    354.  
      }
    355.  
      public float sp2px(float sp){
    356.  
      final float scale = getResources().getDisplayMetrics().scaledDensity;
    357.  
      return sp * scale;
    358.  
      }
    359.  
      public void setProgressTextVisibility(ProgressTextVisibility visibility){
    360.  
      if(visibility == ProgressTextVisibility.Visible){
    361.  
      mIfDrawText = true;
    362.  
      }else{
    363.  
      mIfDrawText = false;
    364.  
      }
    365.  
      invalidate();
    366.  
      }
    367.  
  • 相关阅读:
    岁月静好
    一代才女林徽因 人生若只如初见
    HTML5手机网站开发页面宽度解决方案
    上帝是公平的
    我一直在坚持,你呢?
    让生命更美丽!
    网页跳转,可以任意规定延迟显示的时间
    !important的用法
    小站初建
    GTD之图表
  • 原文地址:https://www.cnblogs.com/xgjblog/p/14101566.html
Copyright © 2011-2022 走看看