亲宝软件园·资讯

展开

Android 进度条 Android常用进度条效果分享

Saflyer 人气:6
想了解Android常用进度条效果讲解的相关内容吗,Saflyer在本文为您仔细讲解Android 进度条的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:进度条,android,下面大家一起来学习吧。

先看看效果:

activity_main.xml主页布局就2个button,分别弹出不同效果的2个进度条

<LinearLayout 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"
 tools:context="com.example.dialog.MainActivity" >
 <Button
  android:id="@+id/button1"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/hello_world" />
  <Button
  android:id="@+id/button2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/hello_world" />
</LinearLayout>

MainActivity

package com.example.dialog;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
public class MainActivity extends FragmentActivity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  findViewById(R.id.button1).setOnClickListener(
    new View.OnClickListener() {
     @Override
     public void onClick(View v) {
      MyloadDialog myloadDialog = new MyloadDialog(
        MainActivity.this, 1);
      myloadDialog.show();
     }
    });

  findViewById(R.id.button2).setOnClickListener(
    new View.OnClickListener() {
     @Override
     public void onClick(View v) {
      MyloadDialog myloadDialog = new MyloadDialog(
        MainActivity.this, 2);
      myloadDialog.show();
     }
    });
 }
}

MyloadDialog

package com.example.dialog;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class MyloadDialog extends Dialog{

 public MyloadDialog(Context context,int args) {
   super(context, R.style.PerfectDialog); 
   init(args);
 }
  private int barColor = Color.parseColor("#ff009688");

  private void init(int args) { 
   if (args == 1) {
   View contentView = View.inflate(getContext(),
     R.layout.dialog_load_classic_layout, null);
   setContentView(contentView);
   LoadClassicView loadClassicView = (LoadClassicView) contentView
     .findViewById(R.id.dialogLoadView);
   loadClassicView.startLoad();
  }else if (args == 2) {

   View contentView = View.inflate(getContext(),
     R.layout.dialog_load_material_layout, null);
   setContentView(contentView);



    LoadMaterialView progressWheel = (LoadMaterialView) contentView.findViewById(R.id.dialogLoadView);
    progressWheel.setBarColor(barColor);
    progressWheel.spin();
  }

  } 
}

 </style>


  <style name="PerfectDialog" parent="@android:style/Theme.Dialog">
  <item name="android:windowIsFloating">true</item>//是否浮现在activity之上
  <item name="android:windowIsTranslucent">false</item>//是否半透明
  <item name="android:windowNoTitle">true</item>//是否显示title标题
  <item name="android:windowFrame">@null</item>//设置windowFrame框
  <item name="android:windowFullscreen">false</item>//是否全屏显示
  <item name="android:windowBackground">@android:color/transparent</item>//设置dialog的背景
  <item name="android:windowAnimationStyle">@style/DialogAnims</item>//设置窗口动画效果
  <item name="android:backgroundDimEnabled">true</item>//背景是否变暗
  <item name="android:backgroundDimAmount">0.5</item>//设置背景变暗程度
  <item name="android:windowCloseOnTouchOutside">false</item>
  <item name="android:background">@android:color/transparent</item>
 </style>

  <style name="DialogAnims">
  <item name="android:windowEnterAnimation">@anim/enter</item>//进入动画
  <item name="android:windowExitAnimation">@anim/exit</item>//退出动画
 </style>

enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <alpha
  android:duration="90"
  android:fromAlpha="0"
  android:toAlpha="1"/>
 <scale
  android:duration="135"
  android:fromXScale="0.8"
  android:toXScale="1.05"
  android:fromYScale="0.8"
  android:toYScale="1.05"
  android:pivotX="50%"
  android:pivotY="50%"/>
 <scale
  android:duration="105"
  android:fromXScale="1.05"
  android:toXScale="0.95"
  android:fromYScale="1.05"
  android:toYScale="0.95"
  android:startOffset="135"
  android:pivotX="50%"
  android:pivotY="50%"/>
 <scale
  android:duration="135"
  android:fromXScale="0.95"
  android:toXScale="1"
  android:fromYScale="0.95"
  android:toYScale="1"
  android:startOffset="240"
  android:pivotX="50%"
  android:pivotY="50%"/>
</set>

exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
 <alpha
  android:duration="200"
  android:fromAlpha="1"
  android:toAlpha="0"/>
 <scale
  android:duration="200"
  android:fromXScale="1"
  android:toXScale="0.1"
  android:fromYScale="1"
  android:toYScale="0.1"
  android:pivotX="50%"
  android:pivotY="50%"/>
</set>

  首先看带第一个效果图的布局文件
dialog_load_classic_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="@drawable/background_round_corner"
 android:padding="35dp">

 <com.example.dialog.LoadClassicView
  android:id="@+id/dialogLoadView"
  android:layout_width="45dp"
  android:layout_height="45dp" />

</LinearLayout>

背景圆角background_round_corner.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
 android:shape="rectangle">
 <corners android:radius="8dp"/>
 <solid android:color="#ffffff"/>
</shape>

LoadClassicView

package com.example.dialog;

import android.animation.ArgbEvaluator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;

/**
 * Created by dandy on 2016/5/31.
 */
public class LoadClassicView extends View {

 private static final String TAG = "LoadingView";

 private static final long DELAY_DURATION = 65;

 private static final float SIZE = 22f;//默认大小

 private static final float RAIDUS = 18f;//内部圆半径

 private static final int START_COLOR = Color.parseColor("#5a5a5a");//起始颜色

 private static final int END_COLOR = Color.parseColor("#dddddd");//结束颜色

 private static final int COUNT = 12;//默认加载条个数

 private static final float STROKE_WIDTH = 6.0f;//加载条粗值

 private float size = SIZE;

 private float radius = RAIDUS;

 private int startColor = START_COLOR;

 private int endColor = END_COLOR;

 private int count = COUNT;

 private float strokeWidth = STROKE_WIDTH;

 private DisplayMetrics dm;

 private ArgbEvaluator colorEvaluator;

 private int [] colors;//加载条颜色

 private LoadingLine [] loadingLines;//加载条集合

 private Paint paint;

 private double startAngle = 0;

 private int exactlySize;

 private int startIndex = 0;

 /**
  * 构造方法
  * @param context
  */
 public LoadClassicView(Context context){
  this(context, null);
 }

 public LoadClassicView(Context context, AttributeSet attributeSet){
  super(context, attributeSet);
  setUpInit(attributeSet);
 }

 private void setUpInit(AttributeSet set){
  dm = Resources.getSystem().getDisplayMetrics();
  paint = new Paint();
  paint.setAntiAlias(true);
  paint.setStrokeWidth(strokeWidth);
  paint.setStrokeCap(Paint.Cap.ROUND);
  initColor();
  initLoadingLines();
 }

 /*
  * 初始化每个的颜色
  */
 private void initColor(){
  colorEvaluator = new ArgbEvaluator();
  colors = new int[count];
  for(int i = 0;i < count;i++){
   colors[i] = (Integer)colorEvaluator.evaluate(i*1.0f/(count-1),startColor,endColor);

  }
 }

 /**
  * 为每个赋值颜色值
  */
 private void initLoadingLines(){
  loadingLines = new LoadingLine[count];
  for(int i = 0;i <count;i++){
   LoadingLine loadingLine = new LoadingLine();
   loadingLine.drawColor = colors[i];
   loadingLines[i] = loadingLine;
  }
 }

 /**
  * 设置显示颜色
  * @param index,线段颜色初始化位置
  */
 private void setColor(int index){
  int lineIndex;
  for(int i = 0;i < count;i++){
   lineIndex = index + i;
   loadingLines[lineIndex >= count?lineIndex - count:lineIndex].drawColor = colors[i];
  }
 }


 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  /**计算宽**/
  final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  int width = MeasureSpec.getSize(widthMeasureSpec);
  if(widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST){
   width = applyDimension(size);
  }

  /**计算高**/
  final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  int height = MeasureSpec.getSize(heightMeasureSpec);
  if (heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST) {
   height = applyDimension(size);
  }

  /**
   * 取小的值作为控件的大小
   */
  exactlySize = width >= height ? height:width;

  this.radius = 0.22f * exactlySize;

  setMeasuredDimension(exactlySize,exactlySize);

 }

 @Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  float delayAngle = 360.0f / count;
  LoadingLine loadingLine;
  double value;
  for(int i = 0;i < count;i++){
   loadingLine = loadingLines[i];
   value = startAngle * Math.PI / 180;
   loadingLine.startX = (int) Math.round(radius * Math.cos(value));
   loadingLine.startY = (int) Math.round(radius * Math.sin(value));
   loadingLine.endX = (int) Math.round(exactlySize / 2.5f * Math.cos(value));
   loadingLine.endY = (int) Math.round(exactlySize / 2.5f * Math.sin(value));
   startAngle += delayAngle;
  }
  startAngle = 0;
 }

 @Override
 protected void onDraw(Canvas canvas) {
  canvas.save();
  canvas.translate(exactlySize/2.0f,exactlySize/2.0f);
  for(int i = 0; i < count;i++){
   LoadingLine loadingLine = loadingLines[i];
   paint.setColor(loadingLine.drawColor);
   canvas.drawLine(loadingLine.startX, loadingLine.startY, loadingLine.endX, loadingLine.endY, paint);
  }
  canvas.restore();
 }

 public void startLoad(){
  postDelayed(runnable,100);
 }

 public void finishLoad(){
  removeCallbacks(runnable);
 }

 private Runnable runnable = new Runnable() {
  @Override
  public void run() {
   postInvalidate();
   removeCallbacks(runnable);
   setColor(startIndex % count);
   startIndex++;
   postDelayed(runnable,DELAY_DURATION);
  }
 };

 /**
  * px2dp
  * @param value
  */
 private int applyDimension(float value){
  return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm);
 }

 private static class LoadingLine{
  private int drawColor;
  private int startX;
  private int startY;
  private int endX;
  private int endY;
 }
}

接下来看第二个图片
dialog_load_material_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:orientation="vertical"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="@drawable/background_round_corner"
 android:padding="35dp">
 <com.example.dialog.LoadMaterialView
  android:id="@id/dialogLoadView"
  android:layout_width="45dp"
  android:layout_height="45dp" />
</LinearLayout>

LoadMaterialView

package com.example.dialog;

/**
 * Created by Seeker on 2016/8/4.
 *
 * @copy https://github.com/pnikosis/materialish-progress
 */

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;



public class LoadMaterialView extends View {

 private static final String TAG = "ProgressWheel";

 private final int barLength = 16;
 private final int barMaxLength = 270;
 private final long pauseGrowingTime = 200;
 /**
  * *********
  * DEFAULTS *
  * **********
  */
 //Sizes (with defaults in DP)
 private int circleRadius = 28;
 private int barWidth = 4;
 private int rimWidth = 4;
 private boolean fillRadius = false;
 private double timeStartGrowing = 0;
 private double barSpinCycleTime = 460;
 private float barExtraLength = 0;
 private boolean barGrowingFromFront = true;
 private long pausedTimeWithoutGrowing = 0;
 //Colors (with defaults)
 private int barColor = 0xAA000000;
 private int rimColor = 0x00FFFFFF;

 //Paints
 private Paint barPaint = new Paint();
 private Paint rimPaint = new Paint();

 //Rectangles
 private RectF circleBounds = new RectF();

 //Animation
 //The amount of degrees per second
 private float spinSpeed = 230.0f;
 //private float spinSpeed = 120.0f;
 // The last time the spinner was animated
 private long lastTimeAnimated = 0;

 private boolean linearProgress;

 private float mProgress = 0.0f;
 private float mTargetProgress = 0.0f;
 private boolean isSpinning = false;

 private ProgressCallback callback;

 private boolean shouldAnimate;

 /**
  * The constructor for the ProgressWheel
  */
 public LoadMaterialView(Context context, AttributeSet attrs) {
  super(context, attrs);

  parseAttributes(context.obtainStyledAttributes(attrs, R.styleable.LoadMaterialView));

  setAnimationEnabled();
 }

 /**
  * The constructor for the ProgressWheel
  */
 public LoadMaterialView(Context context) {
  super(context);
  setAnimationEnabled();
 }

 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
 private void setAnimationEnabled() {
  int currentApiVersion = Build.VERSION.SDK_INT;

  float animationValue;
  if (currentApiVersion >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
   animationValue = Settings.Global.getFloat(getContext().getContentResolver(),
     Settings.Global.ANIMATOR_DURATION_SCALE, 1);
  } else {
   animationValue = Settings.System.getFloat(getContext().getContentResolver(),
     Settings.System.ANIMATOR_DURATION_SCALE, 1);
  }

  shouldAnimate = animationValue != 0;
 }

 //----------------------------------
 //Setting up stuff
 //----------------------------------

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);

  int viewWidth = circleRadius + this.getPaddingLeft() + this.getPaddingRight();
  int viewHeight = circleRadius + this.getPaddingTop() + this.getPaddingBottom();

  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  int heightSize = MeasureSpec.getSize(heightMeasureSpec);

  int width;
  int height;

  //Measure Width
  if (widthMode == MeasureSpec.EXACTLY) {
   //Must be this size
   width = widthSize;
  } else if (widthMode == MeasureSpec.AT_MOST) {
   //Can't be bigger than...
   width = Math.min(viewWidth, widthSize);
  } else {
   //Be whatever you want
   width = viewWidth;
  }

  //Measure Height
  if (heightMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.EXACTLY) {
   //Must be this size
   height = heightSize;
  } else if (heightMode == MeasureSpec.AT_MOST) {
   //Can't be bigger than...
   height = Math.min(viewHeight, heightSize);
  } else {
   //Be whatever you want
   height = viewHeight;
  }

  setMeasuredDimension(width, height);
 }

 /**
  * Use onSizeChanged instead of onAttachedToWindow to get the dimensions of the view,
  * because this method is called after measuring the dimensions of MATCH_PARENT & WRAP_CONTENT.
  * Use this dimensions to setup the bounds and paints.
  */
 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);

  setupBounds(w, h);
  setupPaints();
  invalidate();
 }

 /**
  * Set the properties of the paints we're using to
  * draw the progress wheel
  */
 private void setupPaints() {
  barPaint.setColor(barColor);
  barPaint.setAntiAlias(true);
  barPaint.setStyle(Style.STROKE);
  barPaint.setStrokeWidth(barWidth);

  rimPaint.setColor(rimColor);
  rimPaint.setAntiAlias(true);
  rimPaint.setStyle(Style.STROKE);
  rimPaint.setStrokeWidth(rimWidth);
 }

 /**
  * Set the bounds of the component
  */
 private void setupBounds(int layout_width, int layout_height) {
  int paddingTop = getPaddingTop();
  int paddingBottom = getPaddingBottom();
  int paddingLeft = getPaddingLeft();
  int paddingRight = getPaddingRight();

  if (!fillRadius) {
   // Width should equal to Height, find the min value to setup the circle
   int minValue = Math.min(layout_width - paddingLeft - paddingRight,
     layout_height - paddingBottom - paddingTop);

   int circleDiameter = Math.min(minValue, circleRadius * 2 - barWidth * 2);

   // Calc the Offset if needed for centering the wheel in the available space
   int xOffset = (layout_width - paddingLeft - paddingRight - circleDiameter) / 2 + paddingLeft;
   int yOffset = (layout_height - paddingTop - paddingBottom - circleDiameter) / 2 + paddingTop;

   circleBounds =
     new RectF(xOffset + barWidth, yOffset + barWidth, xOffset + circleDiameter - barWidth,
       yOffset + circleDiameter - barWidth);
  } else {
   circleBounds = new RectF(paddingLeft + barWidth, paddingTop + barWidth,
     layout_width - paddingRight - barWidth, layout_height - paddingBottom - barWidth);
  }
 }

 /**
  * Parse the attributes passed to the view from the XML
  *
  * @param a the attributes to parse
  */
 private void parseAttributes(TypedArray a) {
  // We transform the default values from DIP to pixels
  DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
  barWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, barWidth, metrics);
  rimWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rimWidth, metrics);
  circleRadius =
    (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, circleRadius, metrics);

  circleRadius =
    (int) a.getDimension(R.styleable.LoadMaterialView_matProg_circleRadius, circleRadius);

  fillRadius = a.getBoolean(R.styleable.LoadMaterialView_matProg_fillRadius, false);

  barWidth = (int) a.getDimension(R.styleable.LoadMaterialView_matProg_barWidth, barWidth);

  rimWidth = (int) a.getDimension(R.styleable.LoadMaterialView_matProg_rimWidth, rimWidth);

  float baseSpinSpeed =
    a.getFloat(R.styleable.LoadMaterialView_matProg_spinSpeed, spinSpeed / 360.0f);
  spinSpeed = baseSpinSpeed * 360;

  barSpinCycleTime =
    a.getInt(R.styleable.LoadMaterialView_matProg_barSpinCycleTime, (int) barSpinCycleTime);

  barColor = a.getColor(R.styleable.LoadMaterialView_matProg_barColor, barColor);

  rimColor = a.getColor(R.styleable.LoadMaterialView_matProg_rimColor, rimColor);

  linearProgress = a.getBoolean(R.styleable.LoadMaterialView_matProg_linearProgress, false);

  if (a.getBoolean(R.styleable.LoadMaterialView_matProg_progressIndeterminate, false)) {
   spin();
  }

  // Recycle
  a.recycle();
 }

 public void setCallback(ProgressCallback progressCallback) {
  callback = progressCallback;

  if (!isSpinning) {
   runCallback();
  }
 }

 //----------------------------------
 //Animation stuff
 //----------------------------------

 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);

  canvas.drawArc(circleBounds, 360, 360, false, rimPaint);

  boolean mustInvalidate = false;

  if (!shouldAnimate) {
   return;
  }

  if (isSpinning) {
   //Draw the spinning bar
   mustInvalidate = true;

   long deltaTime = (SystemClock.uptimeMillis() - lastTimeAnimated);
   float deltaNormalized = deltaTime * spinSpeed / 1000.0f;

   updateBarLength(deltaTime);

   mProgress += deltaNormalized;
   if (mProgress > 360) {
    mProgress -= 360f;

    // A full turn has been completed
    // we run the callback with -1 in case we want to
    // do something, like changing the color
    runCallback(-1.0f);
   }
   lastTimeAnimated = SystemClock.uptimeMillis();

   float from = mProgress - 90;
   float length = barLength + barExtraLength;

   if (isInEditMode()) {
    from = 0;
    length = 135;
   }

   canvas.drawArc(circleBounds, from, length, false, barPaint);
  } else {
   float oldProgress = mProgress;

   if (mProgress != mTargetProgress) {
    //We smoothly increase the progress bar
    mustInvalidate = true;

    float deltaTime = (float) (SystemClock.uptimeMillis() - lastTimeAnimated) / 1000;
    float deltaNormalized = deltaTime * spinSpeed;

    mProgress = Math.min(mProgress + deltaNormalized, mTargetProgress);
    lastTimeAnimated = SystemClock.uptimeMillis();
   }

   if (oldProgress != mProgress) {
    runCallback();
   }

   float offset = 0.0f;
   float progress = mProgress;
   if (!linearProgress) {
    float factor = 2.0f;
    offset = (float) (1.0f - Math.pow(1.0f - mProgress / 360.0f, 2.0f * factor)) * 360.0f;
    progress = (float) (1.0f - Math.pow(1.0f - mProgress / 360.0f, factor)) * 360.0f;
   }

   if (isInEditMode()) {
    progress = 360;
   }

   canvas.drawArc(circleBounds, offset - 90, progress, false, barPaint);
  }

  if (mustInvalidate) {
   invalidate();
  }
 }

 @Override
 protected void onVisibilityChanged(View changedView, int visibility) {
  super.onVisibilityChanged(changedView, visibility);

  if (visibility == VISIBLE) {
   lastTimeAnimated = SystemClock.uptimeMillis();
  }
 }

 private void updateBarLength(long deltaTimeInMilliSeconds) {
  if (pausedTimeWithoutGrowing >= pauseGrowingTime) {
   timeStartGrowing += deltaTimeInMilliSeconds;

   if (timeStartGrowing > barSpinCycleTime) {
    // We completed a size change cycle
    // (growing or shrinking)
    timeStartGrowing -= barSpinCycleTime;
    //if(barGrowingFromFront) {
    pausedTimeWithoutGrowing = 0;
    //}
    barGrowingFromFront = !barGrowingFromFront;
   }

   float distance =
     (float) Math.cos((timeStartGrowing / barSpinCycleTime + 1) * Math.PI) / 2 + 0.5f;
   float destLength = (barMaxLength - barLength);

   if (barGrowingFromFront) {
    barExtraLength = distance * destLength;
   } else {
    float newLength = destLength * (1 - distance);
    mProgress += (barExtraLength - newLength);
    barExtraLength = newLength;
   }
  } else {
   pausedTimeWithoutGrowing += deltaTimeInMilliSeconds;
  }
 }

 /**
  * Check if the wheel is currently spinning
  */

 public boolean isSpinning() {
  return isSpinning;
 }

 /**
  * Reset the count (in increment mode)
  */
 public void resetCount() {
  mProgress = 0.0f;
  mTargetProgress = 0.0f;
  invalidate();
 }

 /**
  * Turn off spin mode
  */
 public void stopSpinning() {
  isSpinning = false;
  mProgress = 0.0f;
  mTargetProgress = 0.0f;
  invalidate();
 }

 /**
  * Puts the view on spin mode
  */
 public void spin() {
  lastTimeAnimated = SystemClock.uptimeMillis();
  isSpinning = true;
  invalidate();
 }

 private void runCallback(float value) {
  if (callback != null) {
   callback.onProgressUpdate(value);
  }
 }

 private void runCallback() {
  if (callback != null) {
   float normalizedProgress = (float) Math.round(mProgress * 100 / 360.0f) / 100;
   callback.onProgressUpdate(normalizedProgress);
  }
 }

 /**
  * Set the progress to a specific value,
  * the bar will be set instantly to that value
  *
  * @param progress the progress between 0 and 1
  */
 public void setInstantProgress(float progress) {
  if (isSpinning) {
   mProgress = 0.0f;
   isSpinning = false;
  }

  if (progress > 1.0f) {
   progress -= 1.0f;
  } else if (progress < 0) {
   progress = 0;
  }

  if (progress == mTargetProgress) {
   return;
  }

  mTargetProgress = Math.min(progress * 360.0f, 360.0f);
  mProgress = mTargetProgress;
  lastTimeAnimated = SystemClock.uptimeMillis();
  invalidate();
 }

 // Great way to save a view's state http://stackoverflow.com/a/7089687/1991053
 @Override
 public Parcelable onSaveInstanceState() {
  Parcelable superState = super.onSaveInstanceState();

  WheelSavedState ss = new WheelSavedState(superState);

  // We save everything that can be changed at runtime
  ss.mProgress = this.mProgress;
  ss.mTargetProgress = this.mTargetProgress;
  ss.isSpinning = this.isSpinning;
  ss.spinSpeed = this.spinSpeed;
  ss.barWidth = this.barWidth;
  ss.barColor = this.barColor;
  ss.rimWidth = this.rimWidth;
  ss.rimColor = this.rimColor;
  ss.circleRadius = this.circleRadius;
  ss.linearProgress = this.linearProgress;
  ss.fillRadius = this.fillRadius;

  return ss;
 }

 @Override
 public void onRestoreInstanceState(Parcelable state) {
  if (!(state instanceof WheelSavedState)) {
   super.onRestoreInstanceState(state);
   return;
  }

  WheelSavedState ss = (WheelSavedState) state;
  super.onRestoreInstanceState(ss.getSuperState());

  this.mProgress = ss.mProgress;
  this.mTargetProgress = ss.mTargetProgress;
  this.isSpinning = ss.isSpinning;
  this.spinSpeed = ss.spinSpeed;
  this.barWidth = ss.barWidth;
  this.barColor = ss.barColor;
  this.rimWidth = ss.rimWidth;
  this.rimColor = ss.rimColor;
  this.circleRadius = ss.circleRadius;
  this.linearProgress = ss.linearProgress;
  this.fillRadius = ss.fillRadius;

  this.lastTimeAnimated = SystemClock.uptimeMillis();
 }

 /**
  * @return the current progress between 0.0 and 1.0,
  * if the wheel is indeterminate, then the result is -1
  */
 public float getProgress() {
  return isSpinning ? -1 : mProgress / 360.0f;
 }

 //----------------------------------
 //Getters + setters
 //----------------------------------

 /**
  * Set the progress to a specific value,
  * the bar will smoothly animate until that value
  *
  * @param progress the progress between 0 and 1
  */
 public void setProgress(float progress) {
  if (isSpinning) {
   mProgress = 0.0f;
   isSpinning = false;

   runCallback();
  }

  if (progress > 1.0f) {
   progress -= 1.0f;
  } else if (progress < 0) {
   progress = 0;
  }

  if (progress == mTargetProgress) {
   return;
  }

  // If we are currently in the right position
  // we set again the last time animated so the
  // animation starts smooth from here
  if (mProgress == mTargetProgress) {
   lastTimeAnimated = SystemClock.uptimeMillis();
  }

  mTargetProgress = Math.min(progress * 360.0f, 360.0f);

  invalidate();
 }

 /**
  * Sets the determinate progress mode
  *
  * @param isLinear if the progress should increase linearly
  */
 public void setLinearProgress(boolean isLinear) {
  linearProgress = isLinear;
  if (!isSpinning) {
   invalidate();
  }
 }

 /**
  * @return the radius of the wheel in pixels
  */
 public int getCircleRadius() {
  return circleRadius;
 }

 /**
  * Sets the radius of the wheel
  *
  * @param circleRadius the expected radius, in pixels
  */
 public void setCircleRadius(int circleRadius) {
  this.circleRadius = circleRadius;
  if (!isSpinning) {
   invalidate();
  }
 }

 /**
  * @return the width of the spinning bar
  */
 public int getBarWidth() {
  return barWidth;
 }

 /**
  * Sets the width of the spinning bar
  *
  * @param barWidth the spinning bar width in pixels
  */
 public void setBarWidth(int barWidth) {
  this.barWidth = barWidth;
  if (!isSpinning) {
   invalidate();
  }
 }

 /**
  * @return the color of the spinning bar
  */
 public int getBarColor() {
  return barColor;
 }

 /**
  * Sets the color of the spinning bar
  *
  * @param barColor The spinning bar color
  */
 public void setBarColor(int barColor) {
  this.barColor = barColor;
  setupPaints();
  if (!isSpinning) {
   invalidate();
  }
 }

 /**
  * @return the color of the wheel's contour
  */
 public int getRimColor() {
  return rimColor;
 }

 /**
  * Sets the color of the wheel's contour
  *
  * @param rimColor the color for the wheel
  */
 public void setRimColor(int rimColor) {
  this.rimColor = rimColor;
  setupPaints();
  if (!isSpinning) {
   invalidate();
  }
 }

 /**
  * @return the base spinning speed, in full circle turns per second
  * (1.0 equals on full turn in one second), this value also is applied for
  * the smoothness when setting a progress
  */
 public float getSpinSpeed() {
  return spinSpeed / 360.0f;
 }

 /**
  * Sets the base spinning speed, in full circle turns per second
  * (1.0 equals on full turn in one second), this value also is applied for
  * the smoothness when setting a progress
  *
  * @param spinSpeed the desired base speed in full turns per second
  */
 public void setSpinSpeed(float spinSpeed) {
  this.spinSpeed = spinSpeed * 360.0f;
 }

 /**
  * @return the width of the wheel's contour in pixels
  */
 public int getRimWidth() {
  return rimWidth;
 }

 /**
  * Sets the width of the wheel's contour
  *
  * @param rimWidth the width in pixels
  */
 public void setRimWidth(int rimWidth) {
  this.rimWidth = rimWidth;
  if (!isSpinning) {
   invalidate();
  }
 }

 public interface ProgressCallback {
  /**
   * Method to call when the progress reaches a value
   * in order to avoid float precision issues, the progress
   * is rounded to a float with two decimals.
   *
   * In indeterminate mode, the callback is called each time
   * the wheel completes an animation cycle, with, the progress value is -1.0f
   *
   * @param progress a double value between 0.00 and 1.00 both included
   */
  public void onProgressUpdate(float progress);
 }

 static class WheelSavedState extends BaseSavedState {
  //required field that makes Parcelables from a Parcel
  public static final Creator<WheelSavedState> CREATOR =
    new Creator<WheelSavedState>() {
     public WheelSavedState createFromParcel(Parcel in) {
      return new WheelSavedState(in);
     }

     public WheelSavedState[] newArray(int size) {
      return new WheelSavedState[size];
     }
    };
  float mProgress;
  float mTargetProgress;
  boolean isSpinning;
  float spinSpeed;
  int barWidth;
  int barColor;
  int rimWidth;
  int rimColor;
  int circleRadius;
  boolean linearProgress;
  boolean fillRadius;

  WheelSavedState(Parcelable superState) {
   super(superState);
  }

  private WheelSavedState(Parcel in) {
   super(in);
   this.mProgress = in.readFloat();
   this.mTargetProgress = in.readFloat();
   this.isSpinning = in.readByte() != 0;
   this.spinSpeed = in.readFloat();
   this.barWidth = in.readInt();
   this.barColor = in.readInt();
   this.rimWidth = in.readInt();
   this.rimColor = in.readInt();
   this.circleRadius = in.readInt();
   this.linearProgress = in.readByte() != 0;
   this.fillRadius = in.readByte() != 0;
  }

  @Override
  public void writeToParcel(Parcel out, int flags) {
   super.writeToParcel(out, flags);
   out.writeFloat(this.mProgress);
   out.writeFloat(this.mTargetProgress);
   out.writeByte((byte) (isSpinning ? 1 : 0));
   out.writeFloat(this.spinSpeed);
   out.writeInt(this.barWidth);
   out.writeInt(this.barColor);
   out.writeInt(this.rimWidth);
   out.writeInt(this.rimColor);
   out.writeInt(this.circleRadius);
   out.writeByte((byte) (linearProgress ? 1 : 0));
   out.writeByte((byte) (fillRadius ? 1 : 0));
  }
 }
}

attrs_LoadMaterialView.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="LoadMaterialView">
  <attr name="matProg_progressIndeterminate" format="boolean" />
  <attr name="matProg_barColor" format="color" />
  <attr name="matProg_rimColor" format="color" />
  <attr name="matProg_rimWidth" format="dimension" />
  <attr name="matProg_spinSpeed" format="float" />
  <attr name="matProg_barSpinCycleTime" format="integer" />
  <attr name="matProg_circleRadius" format="dimension" />
  <attr name="matProg_fillRadius" format="boolean" />
  <attr name="matProg_barWidth" format="dimension" />
  <attr name="matProg_linearProgress" format="boolean" />
 </declare-styleable>
</resources>

源码下载:http://xiazai.jb51.net/201610/yuanma/AndroidDialog(jb51.net).rar

加载全部内容

相关教程
猜你喜欢
用户评论