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
加载全部内容