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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android超实用的Toast提示框优化分享

    前言 相信每位Android开发者都用过Toast,都知道是弹出消息的.类似于js里面的alert,C#里面的MesageBox.当然android里面也有dialog,dialog是有焦点的,可与用户交互.而toast是没有焦点的,时间到了自动消失,不能回应用户的交互,下面就跟大家分享下Android中Toast提示框的优化方法. 先看下源码: public class Toast { public static final int LENGTH_SHORT = 0; public stati

  • android微信支付源码分享

    本文为大家分享了android微信支付源码,供大家参考,具体内容如下 参数配置 public static final String APP_ID ; /** 在微信开放平台注册app,微信给分配的id **/ public static final String MCH_ID; /** 申请开通微信支付,成功后微信会给你发一封邮件,给你分配一个商户平台账号,在资料里有商户ID **/ public static final String API_KEY; /** 在微信发给你的那封邮件里,给你

  • Android Zxing生成二维码经典案例分享

    本文实例为大家解析了Zxing生成二维码的经典案例,供大家参考,具体内容如下 1.首先呢,先编译 compile 'com.google.zxing:core:3.2.1' 2.实战 public class QRCode { private static int IMAGE_HALFWIDTH = 50;//宽度值,影响中间图片大小 /** * 生成二维码,默认大小为500*500 * * @return bitmap */ public static Bitmap createQRCode(

  • 分享Android仿刮奖效果控件

    本文实例为大家分享了Android刮刮卡效果控件,供大家参考,具体内容如下 刮刮卡类: package com.reyo.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Paint; import android.gr

  • Android 浏览器的开发实例分享

    本文主要讲解Android浏览器的开发实例,有三部分内容:启动Android默认浏览器.指定浏览器进行访问以及打开本地的html文件.       一.启动Android默认浏览器 Java代码 Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); Uri content_url = Uri.parse("http://www.cnblogs.com"); inte

  • Android登录界面的实现代码分享

    最近由于项目需要,宝宝好久没搞Android啦,又是因为项目需要,现在继续弄Android,哎,说多了都是泪呀,别的不用多说,先搞一个登录界面练练手,登录界面可以说是Android项目中最常用也是最基本的,如果这个都搞不定,那可以直接去跳21世纪楼啦. 废话不多说,先上效果图了,如果大家感觉还不错,请参考实现代码吧. 相信这种渣渣布局对很多人来说太简单啦,直接上布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk

  • Android实现分享功能

    Android应用中能很方便的完成这些功能,很多的应用中都有"分享"功能?如何分享呢?下面给大家说说看. 最近有人问到Android分享功能用那个比较好,使用Android自带的Intent来进行分享还是借助第三方呢,直接上代码: 一.使用Intent直接和第三方应用进行通信: /** * 分享功能 * * @param context * 上下文 * @param activityTitle * Activity的名字 * @param msgTitle * 消息标题 * @para

  • 分享Android中Toast的自定义使用

    1.Toast源码分析 老规矩,我们先去看Toast的源码. Toast有两种显示布局方式,一种最常见调用Toast.makeText()  ,看源码是这样写的 public static Toast makeText(Context context, CharSequence text, @Duration int duration) { Toast result = new Toast(context); LayoutInflater inflate = (LayoutInflater) c

  • Android实现第三方授权登录、分享以及获取用户资料

    由于公司项目的需要,要实现在项目中使用第三方授权登录以及分享文字和图片等这样的效果,几经波折,查阅了一番资料,做了一个Demo.实现起来的效果还是不错的,不敢独享,决定写一个总结的教程,供大家互相交流.学习和参考,只求能和大家共同进步.希望能多多支持! 这篇文章中,我们使用到了Share SDK,它是为iOS.Android.WP8的APP提供社会化功能的一个组件,目前支持如QQ.微信.新浪微博.腾讯微博.开心网.人人网.豆瓣.网易微博.搜狐微博.facebook.twitter.google+

  • Android 实现微信,微博,微信朋友圈,QQ分享的功能

    Android 实现微信,微博,微信朋友圈,QQ分享的功能 一.去各自所在的开发者平台注册相应的Key值:引入相关jar包.权限等 二.ShareUtil工具类 import android.app.Activity; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bit

  • Android获取高清app图标代码分享

    Android获取高清app图标只有一个方法,具体内容如下 public synchronized static Drawable getIconFromPackageName(String packageName, Context context) { PackageManager pm = context.getPackageManager(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)

  • 分享一个Android设置圆形图片的特别方法

    Cardview配合ImageView显示圆形图效果图: 刚在看自定义View的知识点时,突然想起来,如果CardView宽高相等,CardView设置圆角的半径为宽高的一半时,不就是一个圆形嘛?! 1.布局文件 <android.support.v7.widget.CardView android:id="@+id/cv_img_activity" android:layout_width="200dp" android:layout_height=&quo

随机推荐