53

我想自定义圆形进度条,就像在 google play shop中下载西装外套应用程序一样。我希望像下面的屏幕截图:

在此处输入图像描述

有人帮我怎么做吗?

4

9 回答 9

34

我在网上找到的最好的两个库在 github 上:

希望对你有帮助

于 2013-07-23T21:08:18.843 回答
32

我遇到了同样的问题,但没有找到适合我的情况的解决方案,所以我决定换一种方式。我创建了自定义可绘制类。在这个类中,我为进度线和背景线创建了 2 个油漆(有一些更大的笔划)。首先在构造函数中设置 startAngle 和 sweepAngle:

    mSweepAngle = 0;
    mStartAngle = 270;

这是此类的 onDraw 方法:

@Override
public void draw(Canvas canvas) {
    // draw background line
    canvas.drawArc(mRectF, 0, 360, false, mPaintBackground);
    // draw progress line
    canvas.drawArc(mRectF, mStartAngle, mSweepAngle, false, mPaintProgress);
}

所以现在你需要做的就是将此drawable设置为视图的背景,在后台线程更改sweepAngle:

mSweepAngle += 360 / totalTimerTime // this is mStep

并在具有此可绘制对象作为背景的视图上以一定的时间间隔(例如,如果您想要平滑的进度更改,则每 1 秒或更频繁)直接调用 InvalidateSelf()。而已!

PS我知道,我知道......当然你想要更多的代码。所以这里都是流程:

  1. 创建 XML 视图:

     <View
     android:id="@+id/timer"
     android:layout_width="match_parent"
     android:layout_height="match_parent"/>
    
  2. 创建和配置自定义可绘制类(如上所述)。不要忘记为线条设置油漆。这里绘制进度线:

    mPaintProgress = new Paint();
    mPaintProgress.setAntiAlias(true);
    mPaintProgress.setStyle(Paint.Style.STROKE);
    mPaintProgress.setStrokeWidth(widthProgress);
    mPaintProgress.setStrokeCap(Paint.Cap.ROUND);
    mPaintProgress.setColor(colorThatYouWant);
    

背景油漆也一样(如果你愿意,可以多设置一点宽度)

  1. 在drawable类中create方法进行更新(上面描述的Step计算)

    public void update() {
        mSweepAngle += mStep;
        invalidateSelf();
    }
    
  2. 将此可绘制类设置为 YourTimerView(我是在运行时完成的)- 使用上面 xml 中的 @+id/timer 查看:

    OurSuperDrawableClass superDrawable = new OurSuperDrawableClass(); YourTimerView.setBackgroundDrawable(superDrawable);

  3. 使用可运行和更新视图创建后台线程:

    YourTimerView.post(new Runnable() {
        @Override
        public void run() {
            // update progress view
            superDrawable.update();
        }
    });
    

而已 !享受你很酷的进度条。如果您对这么多的文字感到厌烦,这里是结果的屏幕截图。在此处输入图像描述

于 2014-11-07T17:29:24.273 回答
12

Circle Android 自定义进度条

有关如何创建 Circle Android 自定义进度条的更多信息,请查看此链接

步骤 01 您应该在可绘制文件上创建一个 xml 文件以配置进度条的外观。所以我将我的 xml 文件创建为 circular_progress_bar.xml。

<?xml version="1.0" encoding="UTF-8"?>

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="120"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="140">
<item android:id="@android:id/background">
<shape
    android:innerRadiusRatio="3"
    android:shape="ring"
    android:useLevel="false"
     android:angle="0"
     android:type="sweep"
    android:thicknessRatio="50.0">
    <solid android:color="#000000"/>
</shape>

 </item>
 <item android:id="@android:id/progress">
   <rotate
    android:fromDegrees="120"
    android:toDegrees="120">
<shape
    android:innerRadiusRatio="3"
    android:shape="ring"
     android:angle="0"
     android:type="sweep"
    android:thicknessRatio="50.0">
    <solid android:color="#ffffff"/>
</shape>
</rotate>
</item>
</layer-list>

步骤 02 然后在你的 xml 文件上创建进度条然后在你的 drawable 文件夹中给出 xml 文件的名称作为 android:progressDrawable 的一部分

 <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginLeft="0dp"
            android:layout_centerHorizontal="true"
            android:indeterminate="false"
            android:max="100"
            android:progressDrawable="@drawable/circular_progress_bar" />

Step 03 使用线程可视化进度条

package com.example.progress;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu;
import android.view.animation.Animation;
 import android.view.animation.TranslateAnimation;
 import android.widget.ProgressBar;
 import android.widget.TextView;

 public class MainActivity extends Activity {

  private ProgressBar progBar;
  private TextView text;
     private Handler mHandler = new Handler();
     private int mProgressStatus=0;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    progBar= (ProgressBar)findViewById(R.id.progressBar);
    text = (TextView)findViewById(R.id.textView1);

    dosomething();
}



  public void dosomething() {

  new Thread(new Runnable() {
        public void run() {
        final int presentage=0;
            while (mProgressStatus < 63) {
                mProgressStatus += 1;
                // Update the progress bar
                mHandler.post(new Runnable() {
                    public void run() {
                        progBar.setProgress(mProgressStatus);
                        text.setText(""+mProgressStatus+"%");

                    }
                });
                try {



                    Thread.sleep(50);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
  }


 }
于 2015-03-21T12:25:24.540 回答
6

试试这段代码来创建圆形进度条(饼图)。传递它整数值以绘制填充区域的百分比。:)

private void circularImageBar(ImageView iv2, int i) {

    Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(b); 
    Paint paint = new Paint();

        paint.setColor(Color.parseColor("#c4c4c4"));
        paint.setStrokeWidth(10);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(150, 150, 140, paint);
        paint.setColor(Color.parseColor("#FFDB4C"));
        paint.setStrokeWidth(10);   
        paint.setStyle(Paint.Style.FILL);
        final RectF oval = new RectF();
        paint.setStyle(Paint.Style.STROKE);
        oval.set(10,10,290,290);
        canvas.drawArc(oval, 270, ((i*360)/100), false, paint);
        paint.setStrokeWidth(0);    
        paint.setTextAlign(Align.CENTER);
        paint.setColor(Color.parseColor("#8E8E93")); 
        paint.setTextSize(140);
        canvas.drawText(""+i, 150, 150+(paint.getTextSize()/3), paint); 
        iv2.setImageBitmap(b);
}
于 2014-10-30T12:57:43.027 回答
6

一个非常有用的,用于 android 中的自定义进度条。

在您的布局文件中

<com.lylc.widget.circularprogressbar.example.CircularProgressBar
android:id="@+id/mycustom_progressbar"
.
.
.
 />

和Java文件

CircularProgressBar progressBar = (CircularProgressBar) findViewById(R.id.mycustom_progressbar);
progressBar.setTitle("Circular Progress Bar");
于 2014-10-30T05:46:10.307 回答
5

我通过创建自定义视图解决了这个很酷的自定义进度条。我已经重写了 onDraw() 方法来在画布上绘制圆圈、填充弧和文本。

以下是自定义进度条

import android.annotation.TargetApi;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.Rect;

import android.graphics.RectF;

import android.os.Build;

import android.util.AttributeSet;

import android.view.View;

import com.investorfinder.utils.UiUtils;


public class CustomProgressBar extends View {


private int max = 100;

private int progress;

private Path path = new Path();

int color = 0xff44C8E5;

private Paint paint;

private Paint mPaintProgress;

private RectF mRectF;

private Paint textPaint;

private String text = "0%";

private final Rect textBounds = new Rect();

private int centerY;

private int centerX;

private int swipeAndgle = 0;


public CustomProgressBar(Context context) {
    super(context);
    initUI();
}

public CustomProgressBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    initUI();
}

public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initUI();
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    initUI();
}

private void initUI() {
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setStrokeWidth(UiUtils.dpToPx(getContext(), 1));
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(color);


    mPaintProgress = new Paint();
    mPaintProgress.setAntiAlias(true);
    mPaintProgress.setStyle(Paint.Style.STROKE);
    mPaintProgress.setStrokeWidth(UiUtils.dpToPx(getContext(), 9));
    mPaintProgress.setColor(color);

    textPaint = new Paint();
    textPaint.setAntiAlias(true);
    textPaint.setStyle(Paint.Style.FILL);
    textPaint.setColor(color);
    textPaint.setStrokeWidth(2);
}

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

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
    int viewHeight = MeasureSpec.getSize(heightMeasureSpec);

    int radius = (Math.min(viewWidth, viewHeight) - UiUtils.dpToPx(getContext(), 2)) / 2;

    path.reset();

    centerX = viewWidth / 2;
    centerY = viewHeight / 2;
    path.addCircle(centerX, centerY, radius, Path.Direction.CW);

    int smallCirclRadius = radius - UiUtils.dpToPx(getContext(), 7);
    path.addCircle(centerX, centerY, smallCirclRadius, Path.Direction.CW);
    smallCirclRadius += UiUtils.dpToPx(getContext(), 4);

    mRectF = new RectF(centerX - smallCirclRadius, centerY - smallCirclRadius, centerX + smallCirclRadius, centerY + smallCirclRadius);

    textPaint.setTextSize(radius * 0.5f);
}


@Override
protected void onDraw(Canvas canvas) {


    super.onDraw(canvas);

    canvas.drawPath(path, paint);

    canvas.drawArc(mRectF, 270, swipeAndgle, false, mPaintProgress);

    drawTextCentred(canvas);

}

public void drawTextCentred(Canvas canvas) {

    textPaint.getTextBounds(text, 0, text.length(), textBounds);

    canvas.drawText(text, centerX - textBounds.exactCenterX(), centerY - textBounds.exactCenterY(), textPaint);
}

public void setMax(int max) {
    this.max = max;
}

public void setProgress(int progress) {
    this.progress = progress;

    int percentage = progress * 100 / max;

    swipeAndgle = percentage * 360 / 100;

    text = percentage + "%";

    invalidate();
}

public void setColor(int color) {
    this.color = color;
}
}

在布局 XML

<com.your.package.name.CustomProgressBar
            android:id="@+id/progress_bar"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/txt_title"
            android:layout_marginRight="15dp" />

在活动中

CustomProgressBar progressBar = (CustomProgressBar)findViewById(R.id.progress_bar);

    progressBar.setMax(9);

    progressBar.setProgress(5);
于 2016-04-27T10:13:21.680 回答
0

我会创建一个新的视图类并从现有的 ProgressBar 派生。然后重写 onDraw 函数。为此,您将需要对画布进行直接绘制调用,因为它是如此自定义 - drawText、drawArc 和 drawOval 的组合应该做到这一点 - 外环和空部分的椭圆形和弧形部分着色。您可能最终还需要覆盖 onMeasure 和 onLayout。然后在你的xml中,当你想使用它时,像这样通过类名引用这个视图。

于 2013-02-04T13:54:53.107 回答
0

其余代码

utils方法的代码:

public static int[] resourcesIDsToColors(Context context, int[] resIDs){
            int[] colors = new int[resIDs.length];
            for(int i=0; i < resIDs.length; i++){
                colors[i] = ActivityCompat.getColor(context, resIDs[i]);
            }
            return colors;
        }
    
    public static void setSubClassFieldIntValue(Object objField, Class<?> superClass, String subName, String fieldName, int fieldValue){
            Class<?> subClass = getSubClass(superClass, subName);
            if(subClass != null) {
                Field field = getClassField(subClass, fieldName);
                if (field != null) {
                    setFieldValue(objField, field, fieldValue);
                }
            }
        }
    
        public static Class<?> getSubClass(Class<?> superClass, String subName){
            Class<?>[] classes = superClass.getDeclaredClasses();
            if(classes != null && classes.length > 0){
                for(Class<?> clss : classes){
                    if(clss.getSimpleName().equals(subName)){
                        return clss;
                    }
                }
            }
            return null;
        }
    
        public static Field getClassField(Class<?> clss, String fieldName){
            try {
                Field field = clss.getDeclaredField(fieldName);
                field.setAccessible(true);
                return field;
            } catch (NoSuchFieldException nsfE) {
                Log.e(TAG, nsfE.getMessage());
            } catch (SecurityException sE){
                Log.e(TAG, sE.getMessage());
            } catch (Exception e){
                Log.e(TAG, e.getMessage());
            }
            return null;
        }
    
    public static int[][] arrayToMatrix(int[] array, int numColumns){
            int numRows = array.length / numColumns;
            int[][] matrix = new int[numRows][numColumns];
            int nElemens = array.length;
            for(int i=0; i < nElemens; i++){
                matrix[i / numColumns][i % numColumns] = array[i];
            }
            return matrix;
        }

public static int[] matrixToArray(int[][] matrix){
        /** [+] Square matrix of order n        ->      A matrix with n rows and n columns, same number of rows and columns.
         *  [+] Matrix rows & columns number annotations:
         *          matrix[rows][columns]           matrix (rows x columns)         matrix rows, columns        rows by columns matrix
         * **/
        int numRows = matrix.length;
        int[] arr = new int[]{};
        for(int i=0; i < numRows; i++){
            int numColumns = matrix[i].length;
            int[] row = new int[numColumns];
            for(int j=0; j < numColumns; j++){
                row[j] = matrix[i][j];
            }
            arr = ArrayUtils.addAll(arr, row);
        }
        return arr;
    }

默认布局代码:

<?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:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@color/transparent">
    <LinearLayout
        android:id="@+id/layout_progress_bar_only"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:visibility="gone">
        <android.support.constraint.ConstraintLayout
            android:id="@+id/dpb_constraint_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <me.zhanghai.android.materialprogressbar.MaterialProgressBar
                android:id="@+id/dpb_progress_bar"
                android:layout_width="@dimen/pbd_progressbar_width_2"
                android:layout_height="@dimen/pbd_progressbar_height_2"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"/>
            <LinearLayout
                android:id="@+id/dpb_text_container"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"/>
        </android.support.constraint.ConstraintLayout>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/layout_progress_bar_and_msg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:visibility="gone"
        style="@style/PBDTextualMainLayoutStyle">
        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:cardElevation="@dimen/pbd_textual_card_elevation">
            <TextView
                android:id="@+id/pbd_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/PBDTextualTitle"/>
        </android.support.v7.widget.CardView>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/pbd_textual_main_layout_height"
            android:orientation="horizontal">
            <android.support.v7.widget.CardView
                android:layout_width="@dimen/pbd_textual_progressbar_width"
                android:layout_height="@dimen/pbd_textual_progressbar_height">
                <me.zhanghai.android.materialprogressbar.MaterialProgressBar
                    android:id="@+id/dpb_progress_bar_and_msg"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    style="@style/PBDProgressBarStyle"/>
            </android.support.v7.widget.CardView>
            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="@dimen/pbd_textual_msg_container_height">
                <TextView
                    android:id="@+id/dpb_progress_msg"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    style="@style/PBDTextualProgressMsgStyle"/>
            </android.support.v7.widget.CardView>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

进度条环:

<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="300"
            android:toDegrees="660">
            <shape
                android:shape="ring"
                android:useLevel="false">
                <gradient
                    android:type="sweep"/>
            </shape>
        </rotate>
    </item>
    <item>
        <rotate
            android:fromDegrees="210"
            android:toDegrees="570">
            <shape
                android:shape="ring"
                android:useLevel="false">
                <gradient
                    android:type="sweep"/>
            </shape>
        </rotate>
    </item>
    <item>
        <rotate
            android:fromDegrees="120"
            android:toDegrees="480">
            <shape
                android:shape="ring"
                android:useLevel="false">
                <gradient
                    android:type="sweep"
                    android:startColor="#00000000"
                    android:centerColor="#00000000"/>
            </shape>
        </rotate>
    </item>
    <item>
        <rotate
            android:fromDegrees="30"
            android:toDegrees="390">
            <shape
                android:shape="ring"
                android:useLevel="false">
                <solid android:color="#000000"/>
                <gradient
                    android:type="sweep"/>
            </shape>
        </rotate>
    </item>
</layer-list>

维度资源:

 <!-- ProgressBarDialog Dimens (Normal & Textual Versions) -->
        <dimen name="pbd_window_width">250dp</dimen>
        <dimen name="pbd_window_height">250dp</dimen>
        <dimen name="pbd_progressbar_width_1">250dp</dimen>
        <dimen name="pbd_progressbar_height_1">250dp</dimen>
        <dimen name="pbd_progressbar_width_2">400dp</dimen>
        <dimen name="pbd_progressbar_height_2">400dp</dimen>
        <dimen name="pbd_textual_window_height">170dp</dimen>
        <dimen name="pbd_textual_main_layout_height">150dp</dimen>
        <dimen name="pbd_textual_progressbar_width">150dp</dimen>
        <dimen name="pbd_textual_progressbar_height">150dp</dimen>
        <dimen name="pbd_textual_msg_container_height">150dp</dimen>
        <dimen name="pbd_textual_main_layout_margin_horizontal">50dp</dimen>
        <dimen name="pbd_textual_main_layout_padding_horizontal">5dp</dimen>
        <dimen name="pbd_textual_main_layout_padding_bottom">15dp</dimen>
        <dimen name="pbd_textual_title_padding">4dp</dimen>
        <dimen name="pbd_textual_msg_container_margin">3dp</dimen>
        <dimen name="pbd_textual_msg_container_padding">3dp</dimen>
        <dimen name="pbd_textual_card_elevation">15dp</dimen>
        <dimen name="pbd_textual_progressmsg_padding_start">10dp</dimen>
        <dimen name="pbd_inner_radius_30dp">30dp</dimen>
        <dimen name="pbd_inner_radius_60dp">60dp</dimen>
        <dimen name="pbd_inner_radius_90dp">90dp</dimen>
        <dimen name="pbd_inner_radius_120dp">120dp</dimen>
        <dimen name="pbd_thickness_40dp">40dp</dimen>
        <dimen name="pbd_thickness_30dp">30dp</dimen>
        <dimen name="pbd_thickness_25dp">25dp</dimen>
        <dimen name="pbd_thickness_20dp">20dp</dimen>
        <dimen name="pbd_thickness_15dp">15dp</dimen>
        <dimen name="pbd_thickness_10dp">10dp</dimen>

样式资源:

<!-- PROGRESS BAR DIALOG STYLES -->
    <style name="PBDCenterTextStyleWhite">
        <item name="android:textAlignment">center</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
        <item name="android:textStyle">bold|italic</item>
        <item name="android:textColor">@color/material_white</item>
        <item name="android:layout_gravity">center</item>
        <item name="android:gravity">center</item>
    </style>

    <style name="PBDTextualTitle">
        <item name="android:textAlignment">viewStart</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLargeInverse</item>
        <item name="android:textStyle">bold|italic</item>
        <item name="android:textColor">@color/colorAccent</item>
        <item name="android:padding">@dimen/pbd_textual_title_padding</item>
        <item name="android:layout_gravity">start</item>
        <item name="android:gravity">center_vertical|start</item>
        <item name="android:background">@color/colorPrimaryDark</item>
    </style>

    <style name="PBDTextualProgressMsgStyle">
        <item name="android:textAlignment">viewStart</item>
        <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
        <item name="android:textColor">@color/material_black</item>
        <item name="android:textStyle">normal|italic</item>
        <item name="android:paddingStart">@dimen/pbd_textual_progressmsg_padding_start</item>
        <item name="android:layout_gravity">start</item>
        <item name="android:gravity">center_vertical|start</item>
        <item name="android:background">@color/material_yellow_A100</item>
    </style>

    <style name="PBDTextualMainLayoutStyle">
        <item name="android:paddingLeft">@dimen/pbd_textual_main_layout_padding_horizontal</item>
        <item name="android:paddingRight">@dimen/pbd_textual_main_layout_padding_horizontal</item>
        <item name="android:paddingBottom">@dimen/pbd_textual_main_layout_padding_bottom</item>
        <item name="android:background">@color/colorPrimaryDark</item>
    </style>

    <style name="PBDProgressBarStyle">
        <item name="android:layout_gravity">center</item>
        <item name="android:gravity">center</item>
    </style>
于 2019-05-23T13:18:36.513 回答
0

我做了一个简单的类,你可以用它来制作自定义 ProgressBar 对话框。实际上它有 2 个默认布局: - 第一个对话框,没有面板,进度条和动画文本居中 - 第二个普通对话框,面板,进度条,标题和消息

它只是一个类,因此不是您可以在项目中导入的可自定义库,因此您需要复制它并根据需要进行更改。它是一个 DialogFragment 类,但您可以在 Activity 中将其用作普通片段,就像使用 FragmentManager 使用经典片段一样。

对话框类的代码:

public class ProgressBarDialog extends DialogFragment {

private static final String TAG = ProgressBarDialog.class.getSimpleName();
private static final String KEY = TAG.concat(".key");
// Argument Keys
private static final String KEY_DIALOG_TYPE = KEY.concat(".dialogType");
private static final String KEY_TITLE = KEY.concat(".title");
private static final String KEY_PROGRESS_TEXT = KEY.concat(".progressText");
private static final String KEY_CUSTOM_LAYOUT_BUILDER = KEY.concat(".customLayoutBuilder");
// Class Names
private static final String CLASS_GRADIENT_STATE = "GradientState";
// Field Names
private static final String FIELD_THICKNESS = "mThickness";
private static final String FIELD_INNER_RADIUS = "mInnerRadius";

/** Dialog Types **/
private static final int TYPE_PROGRESS_BAR_ONLY_NO_ANIM = 0x0;
private static final int TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM = 0x1;
private static final int TYPE_PROGRESS_BAR_ONLY_FADE_ANIM = 0x2;
private static final int TYPE_PROGRESS_BAR_AND_MSG = 0xF;

/** Animations Values **/
private static final long CENTER_TEXT_VIEWS_ANIMATION_DURATION = 250L;
private static final long CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER = 250L;

private MaterialProgressBar mProgressBar;
private LinearLayout mllTextContainer;
private TextView mtvTitle;
private TextView mtvProgressText;

private List<TextView> mCenterTextViews;
private int mDialogType;
private String mTitle;
private String mProgressText;
private CustomLayoutBuilder mCustomLayoutBuilder;

/** Public Static Factory Methods **/
public static ProgressBarDialog initLayoutProgressBarOnlyNoAnim(String text, CustomLayoutBuilder builder){
    return initLayoutProgressBarOnly(TYPE_PROGRESS_BAR_ONLY_NO_ANIM, text, builder);
}

public static ProgressBarDialog initLayoutProgressBarOnlyRotateAnim(String text, CustomLayoutBuilder builder){
    return initLayoutProgressBarOnly(TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM, text, builder);
}

public static ProgressBarDialog initLayoutProgressBarOnlyFadeAnim(String text, CustomLayoutBuilder builder){
    return initLayoutProgressBarOnly(TYPE_PROGRESS_BAR_ONLY_FADE_ANIM, text, builder);
}

public static ProgressBarDialog initLayoutProgressBarAndMsg(String title, String text, CustomLayoutBuilder builder){
    ProgressBarDialog mInstance = new ProgressBarDialog();
    Bundle args = new Bundle();
    args.putInt(KEY_DIALOG_TYPE, TYPE_PROGRESS_BAR_AND_MSG);
    args.putString(KEY_TITLE, title);
    args.putString(KEY_PROGRESS_TEXT, text);
    args.putParcelable(KEY_CUSTOM_LAYOUT_BUILDER, builder);
    mInstance.setArguments(args);
    return mInstance;
}

/** Private Static Factory Methods **/
private static ProgressBarDialog initLayoutProgressBarOnly(int animation, String text, CustomLayoutBuilder builder){
    ProgressBarDialog mInstance = new ProgressBarDialog();
    Bundle args = new Bundle();
    args.putInt(KEY_DIALOG_TYPE, animation);
    args.putString(KEY_PROGRESS_TEXT, text);
    args.putParcelable(KEY_CUSTOM_LAYOUT_BUILDER, builder);
    mInstance.setArguments(args);
    return mInstance;
}

/** Override Lifecycle Methods **/
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initData();
}

@Override @Nullable
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View view = inflater.inflate(R.layout.dialog_progress_bar, container, false);
    initViews(view);
    if(getContext() != null && mCustomLayoutBuilder != null) {
        mProgressBar.setIndeterminateDrawable(getResources().getDrawable(mCustomLayoutBuilder.getLayoutResID()));
        initShapes();
    }
    return view;
}

private void initShapes(){
    if(mProgressBar.getIndeterminateDrawable() instanceof LayerDrawable) {
        LayerDrawable layerDrawable = (LayerDrawable) mProgressBar.getIndeterminateDrawable();
        for (int i = 0; i < layerDrawable.getNumberOfLayers(); i++) {
            if(layerDrawable.getDrawable(i) instanceof RotateDrawable) {
                RotateDrawable rotateDrawable = (RotateDrawable) layerDrawable.getDrawable(i);
                int[] fromToDeg = mCustomLayoutBuilder.getDegreesMatrixRow(i);
                if(fromToDeg.length > 0){
                    rotateDrawable.setFromDegrees(fromToDeg[CustomLayoutBuilder.INDEX_FROM_DEGREES]);
                    rotateDrawable.setToDegrees(fromToDeg[CustomLayoutBuilder.INDEX_TO_DEGREES]);
                }
                if(rotateDrawable.getDrawable() instanceof GradientDrawable){
                    GradientDrawable gradientDrawable = (GradientDrawable) rotateDrawable.getDrawable();
                    int innerRadius = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getInnerRadius(i));
                    if(mDialogType == TYPE_PROGRESS_BAR_AND_MSG){
                        innerRadius /= 3;
                    }
                    int thickness = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getThickness(i));
                    int[] colors = mCustomLayoutBuilder.getColorsMatrixRow(i);
                    if(colors.length > 0x0){
                        gradientDrawable.setColors(DataUtils.resourcesIDsToColors(this.getContext(), colors));
                    }
                    if(innerRadius != -0x1){
                        DataUtils.setSubClassFieldIntValue(gradientDrawable.getConstantState(), gradientDrawable.getClass(), CLASS_GRADIENT_STATE, FIELD_INNER_RADIUS, innerRadius);
                    }
                    if(thickness != -0x1){
                        DataUtils.setSubClassFieldIntValue(gradientDrawable.getConstantState(), gradientDrawable.getClass(), CLASS_GRADIENT_STATE, FIELD_THICKNESS, thickness);
                    }
                }
            }
        }
    }
}

@Override
public void onStart() {
    super.onStart();
    setWindowSize();
    startAnimation();
}

/** Public Methods **/
public void changeTextViews(String progressText){
    mProgressText = progressText;
    initTextViews();
    startAnimation();
}

public String getProgressText(){
    return mProgressText;
}

/** Private Methods **//** Init Methods **/
private void initData(){
    if(getArguments() != null) {
        if (getArguments().containsKey(KEY_DIALOG_TYPE)) {
            mDialogType = getArguments().getInt(KEY_DIALOG_TYPE);
        }
        if(getArguments().containsKey(KEY_TITLE)){
            mTitle = getArguments().getString(KEY_TITLE);
        }
        if (getArguments().containsKey(KEY_PROGRESS_TEXT)) {
            mProgressText = getArguments().getString(KEY_PROGRESS_TEXT);
        }
        if (getArguments().containsKey(KEY_CUSTOM_LAYOUT_BUILDER)){
            mCustomLayoutBuilder = getArguments().getParcelable(KEY_CUSTOM_LAYOUT_BUILDER);
        }
    }
    mCenterTextViews = new ArrayList<>();
}

private void initViews(View layout){
    if(layout != null){
        switch(mDialogType){
            case TYPE_PROGRESS_BAR_ONLY_NO_ANIM:
            case TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM:
            case TYPE_PROGRESS_BAR_ONLY_FADE_ANIM:
                if(getDialog() != null && getDialog().getWindow() != null) {
                    getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);
                }
                LinearLayout mLayoutProgressBarOnly = layout.findViewById(R.id.layout_progress_bar_only);
                mLayoutProgressBarOnly.setVisibility(LinearLayout.VISIBLE);
                mProgressBar = layout.findViewById(R.id.dpb_progress_bar);
                if(mCustomLayoutBuilder.getProgressBarWidthDimen() != -0x1){
                    ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) mProgressBar.getLayoutParams();
                    lp.width = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getProgressBarWidthDimen());
                    lp.height = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getProgressBarHeightDimen());
                    mProgressBar.setLayoutParams(lp);
                }
                mllTextContainer = layout.findViewById(R.id.dpb_text_container);
                initTextViews();
                break;
            case TYPE_PROGRESS_BAR_AND_MSG:
                LinearLayout mLayoutProgressBarAndMsg = layout.findViewById(R.id.layout_progress_bar_and_msg);
                mLayoutProgressBarAndMsg.setVisibility(LinearLayout.VISIBLE);
                mProgressBar = layout.findViewById(R.id.dpb_progress_bar_and_msg);
                mtvTitle = layout.findViewById(R.id.pbd_title);
                mtvProgressText = layout.findViewById(R.id.dpb_progress_msg);
                initProgressMsg();
                break;
        }
    }
}

private void initTextViews(){
    if(!TextUtils.isEmpty(mProgressText)){
        clearTextContainer();
        for(char digit : mProgressText.toCharArray()){
            TextView tv = new TextView(getContext(), null, 0x0, R.style.PBDCenterTextStyleWhite);
            if(mCustomLayoutBuilder.getProgressMsgColor() != CustomLayoutBuilder.DEFAULT_COLOR && getContext() != null){
                tv.setTextColor(ActivityCompat.getColor(getContext(), mCustomLayoutBuilder.getProgressMsgColor()));
            }
            if(mCustomLayoutBuilder.getProgressMsgDimen() != CustomLayoutBuilder.DEFAULT_DIMEN){
                tv.setTextSize(getResources().getDimension(mCustomLayoutBuilder.getProgressMsgDimen()));
            }
            tv.setText(String.valueOf(digit));
            mCenterTextViews.add(tv);
            mllTextContainer.addView(tv);
        }
    }
}

private void initProgressMsg(){
    mtvTitle.setText(mTitle);
    mtvProgressText.setText(mProgressText);
    if(mCustomLayoutBuilder.getProgressMsgColor() != CustomLayoutBuilder.DEFAULT_COLOR){
        mtvProgressText.setTextColor(mCustomLayoutBuilder.getProgressMsgColor());
    }
    if(mCustomLayoutBuilder.getProgressMsgDimen() != CustomLayoutBuilder.DEFAULT_DIMEN){
        mtvProgressText.setTextSize(getResources().getDimension(mCustomLayoutBuilder.getProgressMsgDimen()));
    }
}

private void clearTextContainer(){
    if(mllTextContainer.getChildCount() >= 0x0){
        for(int i=0; i < mllTextContainer.getChildCount(); i++){
            View v = mllTextContainer.getChildAt(i);
            if(v instanceof TextView){
                TextView tv = (TextView) v;
                if(tv.getAnimation() != null){
                    tv.clearAnimation();
                }
            }
        }
    }
    mllTextContainer.removeAllViews();
}

private void setWindowSize(){
    Dialog dialog = getDialog();
    if(dialog != null && dialog.getWindow() != null){
        int width = 0x0, height = 0x0;
        switch(mDialogType){
            case TYPE_PROGRESS_BAR_ONLY_NO_ANIM:
            case TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM:
            case TYPE_PROGRESS_BAR_ONLY_FADE_ANIM:
                width = ViewGroup.LayoutParams.WRAP_CONTENT;        //getResources().getDimensionPixelSize(R.dimen.pbd_window_width);
                height = ViewGroup.LayoutParams.WRAP_CONTENT;       //getResources().getDimensionPixelSize(R.dimen.pbd_window_height);
                break;
            case TYPE_PROGRESS_BAR_AND_MSG:
                width = ViewGroup.LayoutParams.MATCH_PARENT;
                height = ViewGroup.LayoutParams.WRAP_CONTENT;       //getResources().getDimensionPixelSize(R.dimen.pbd_textual_window_height);
                break;
        }
        dialog.getWindow().setLayout(width, height);
    }
}

/** Animation Methods **/
private void startAnimation(){
    switch(mDialogType){
        case TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM:
        startRotateAnimations();
        break;
        case TYPE_PROGRESS_BAR_ONLY_FADE_ANIM:
        startFadeInAnimations();
        break;
    }
}

private void startRotateAnimations(){
    for(TextView tv : mCenterTextViews){
        if(tv != null && tv.getText() != null && !TextUtils.isEmpty(tv.getText().toString().trim())) {
            int i = mCenterTextViews.indexOf(tv);
            RotateAnimation anim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            anim.setDuration(CENTER_TEXT_VIEWS_ANIMATION_DURATION);
            anim.setFillAfter(true);
            anim.setStartOffset(CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER * i);
            if (i == (mCenterTextViews.size() - 0x1)) {
                anim.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        startRotateAnimations();
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
            }
            tv.startAnimation(anim);
        }
    }
}

private void startFadeInAnimations(){
    for(TextView tv : mCenterTextViews){
        if(tv != null && tv.getText() != null && !TextUtils.isEmpty(tv.getText().toString().trim())) {
            int i = mCenterTextViews.indexOf(tv);
            AlphaAnimation anim = new AlphaAnimation(0x1, 0x0);
            anim.setDuration(CENTER_TEXT_VIEWS_ANIMATION_DURATION);
            anim.setFillAfter(true);
            anim.setStartOffset(CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER * i);
            if (i == (mCenterTextViews.size() - 0x1)) {
                anim.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        startFadeOutAnimations();
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
            }
            tv.startAnimation(anim);
        }
    }
}

private void startFadeOutAnimations(){
    for(TextView tv : mCenterTextViews){
        int i = mCenterTextViews.indexOf(tv);
        AlphaAnimation anim = new AlphaAnimation(0x0, 0x1);
        anim.setDuration(CENTER_TEXT_VIEWS_ANIMATION_DURATION);
        anim.setFillAfter(true);
        anim.setStartOffset(CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER * i);
        if(i == (mCenterTextViews.size() - 0x1)){
            anim.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    startFadeInAnimations();
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
        }
        tv.startAnimation(anim);
    }
}

/** Progress Bar Custom Layout Builder Class **/
public static class CustomLayoutBuilder implements Parcelable {

    /** Shapes **/
    private static final int RING = GradientDrawable.RING;

    /** Colors **/
    private static final int[][] COLORS_MATRIX_RYGB = new int[][]{
        new int[]{ R.color.transparent, R.color.transparent, R.color.material_red_A700 },
        new int[]{ R.color.transparent, R.color.transparent, R.color.material_amber_A700 },
        new int[]{ R.color.transparent, R.color.transparent, R.color.material_light_green_A700 },
        new int[]{ R.color.transparent, R.color.transparent, R.color.material_blue_A700 }
    };
    private static final int DEFAULT_COLOR = -0x1;

    /** Dimens **/
    private static final int DEFAULT_DIMEN = -0x1;
    private static final int[] DEFAULT_PROGRESS_BAR_DIMEN = new int[]{};

    /** Indexes **/
    private static final int INDEX_PROGRESS_BAR_WIDTH = 0x0;
    private static final int INDEX_PROGRESS_BAR_HEIGHT = 0x1;
    private static final int INDEX_FROM_DEGREES = 0x0;
    private static final int INDEX_TO_DEGREES = 0x1;

    /** Arrays Sizes **/
    private static final int SIZE_PROGRESS_BAR_DIMENS_ARRAY = 0x2;

    /** Matrix Columns Number **/
    private static final int NUM_COLUMNS_DEGREES_MATRIX = 0x2;      /* Degrees Matrix Index                     ->  degrees[3]  =   { fromDegrees, toDegrees } */
    private static final int NUM_COLUMNS_COLORS_MATRIX = 0x3;       /* GradientDrawable Colors Matrix Index     ->  colors[3]   =   { startColor, centerColor, endColor } */

    /** Drawables Layout Resource IDs **/
    private static final int LAYOUT_RES_PROGRESS_BAR_RINGS = R.drawable.progress_bar_rings;

    /** Layout Data: Four Rings Overlaid **/
    private static final int RINGS_OVERLAID_LAYERS = 0x4;
    private static final int[][] RINGS_OVERLAID_DEGREES = new int[][]{ new int[]{ 300, 660 }, new int[]{ 210, 570 }, new int[]{ 120, 480 }, new int[]{ 30, 390 } };
    private static final int[] RINGS_OVERLAID_SHAPES = new int[]{ RING, RING, RING, RING };
    private static final int[] RINGS_OVERLAID_INNER_RADIUS = new int[]{ R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_60dp};
    private static final int[] RINGS_OVERLAID_THICKNESS = new int[]{ R.dimen.pbd_thickness_40dp, R.dimen.pbd_thickness_30dp, R.dimen.pbd_thickness_20dp, R.dimen.pbd_thickness_10dp };

    /** Layout Data: Four Rings Spaced **/
    private static final int RINGS_SPACED_LAYERS = 0x4;
    private static final int[][] RINGS_SPACED_DEGREES = new int[][]{ new int[]{ 180, 540 }, new int[]{ 0, 360 }, new int[]{ 90, 450 }, new int[]{ 270, 630 } };
    private static final int[] RINGS_SPACED_SHAPES = new int[]{ RING, RING, RING, RING };
    private static final int[] RINGS_SPACED_INNER_RADIUS = new int[]{ R.dimen.pbd_inner_radius_30dp, R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_90dp, R.dimen.pbd_inner_radius_120dp };
    private static final int[] RINGS_SPACED_THICKNESS = new int[]{ R.dimen.pbd_thickness_10dp, R.dimen.pbd_thickness_15dp, R.dimen.pbd_thickness_20dp, R.dimen.pbd_thickness_25dp };

    private int mLayoutResID;
    private int[] mProgressBarDimens;
    private int mNumLayers;
    private int[][] mRotateDegrees;
    private int[] mShapes;
    private int[] mInnerRadius;
    private int[] mThickness;
    private int[][] mColors;
    private int mProgressMsgColor;
    private int mProgressMsgDimen;

    public static Parcelable.Creator CREATOR = new CreatorCustomLayoutBuilder();

    /** Constructors **/
    private CustomLayoutBuilder(int layoutResID, int[] progressBarDimens, int numLayers, int[][] degreesMatrix, int[] shapes, int[] innerRadius, int[] thickness,
                                int[][] colorsMatrix, int msgColor, int progressMsgDimen){
        mLayoutResID = layoutResID;
        mProgressBarDimens = progressBarDimens;
        mNumLayers = numLayers;
        mRotateDegrees = degreesMatrix;
        mShapes = shapes;
        mInnerRadius = innerRadius;
        mThickness = thickness;
        mColors = colorsMatrix;
        mProgressMsgColor = msgColor;
        mProgressMsgDimen = progressMsgDimen;
    }

    private CustomLayoutBuilder(Parcel in){
        mLayoutResID = in.readInt();
        mProgressBarDimens = new int[SIZE_PROGRESS_BAR_DIMENS_ARRAY];
        in.readIntArray(mProgressBarDimens);
        mNumLayers = in.readInt();
        int[] tempArray = new int[NUM_COLUMNS_DEGREES_MATRIX * mNumLayers];
        in.readIntArray(tempArray);
        mRotateDegrees = DataUtils.arrayToMatrix(tempArray, NUM_COLUMNS_DEGREES_MATRIX);
        mShapes = new int[mNumLayers];
        in.readIntArray(mShapes);
        mInnerRadius = new int[mNumLayers];
        in.readIntArray(mInnerRadius);
        mThickness = new int[mNumLayers];
        in.readIntArray(mThickness);
        tempArray = new int[NUM_COLUMNS_COLORS_MATRIX * mNumLayers];
        in.readIntArray(tempArray);
        mColors = DataUtils.arrayToMatrix(tempArray, NUM_COLUMNS_COLORS_MATRIX);
        mProgressMsgColor = in.readInt();
        mProgressMsgDimen = in.readInt();
    }

    /** Public Static Factory Methods **/
    public static CustomLayoutBuilder initLayoutRingsOverlaid(){
        return new CustomLayoutBuilder(LAYOUT_RES_PROGRESS_BAR_RINGS, DEFAULT_PROGRESS_BAR_DIMEN, RINGS_OVERLAID_LAYERS, RINGS_OVERLAID_DEGREES, RINGS_OVERLAID_SHAPES,
                RINGS_OVERLAID_INNER_RADIUS, RINGS_OVERLAID_THICKNESS, COLORS_MATRIX_RYGB, R.color.material_white, DEFAULT_DIMEN);
    }

    public static CustomLayoutBuilder initLayoutRingsOverlaid(int[] resProgBarDimens, int resProgMsgColor, int resProgMsgDimen){
        return new CustomLayoutBuilder(LAYOUT_RES_PROGRESS_BAR_RINGS, resProgBarDimens, RINGS_OVERLAID_LAYERS, RINGS_OVERLAID_DEGREES, RINGS_OVERLAID_SHAPES,
                RINGS_OVERLAID_INNER_RADIUS, RINGS_OVERLAID_THICKNESS, COLORS_MATRIX_RYGB, resProgMsgColor, resProgMsgDimen);
    }

    public static CustomLayoutBuilder initLayoutRingsSpaced(){
        return new CustomLayoutBuilder(LAYOUT_RES_PROGRESS_BAR_RINGS, DEFAULT_PROGRESS_BAR_DIMEN, RINGS_SPACED_LAYERS, RINGS_SPACED_DEGREES, RINGS_SPACED_SHAPES,
                RINGS_SPACED_INNER_RADIUS, RINGS_SPACED_THICKNESS, COLORS_MATRIX_RYGB, DEFAULT_COLOR, DEFAULT_DIMEN);
    }

    /** Override Parcelable Methods **/
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mLayoutResID);
        out.writeIntArray(mProgressBarDimens);
        out.writeInt(mNumLayers);
        out.writeIntArray(DataUtils.matrixToArray(mRotateDegrees));
        out.writeIntArray(mShapes);
        out.writeIntArray(mInnerRadius);
        out.writeIntArray(mThickness);
        out.writeIntArray(DataUtils.matrixToArray(mColors));
        out.writeInt(mProgressMsgColor);
        out.writeInt(mProgressMsgDimen);
    }

    /** Getter & Setter Methods **/
    private int getLayoutResID() {
        return mLayoutResID;
    }

    private void setLayoutResID(int layoutResID) {
        this.mLayoutResID = layoutResID;
    }

    private int[] getProgressBarDimens() {
        return mProgressBarDimens;
    }

    private void setProgressBarDimens(int[] progressBarDimens) {
        this.mProgressBarDimens = progressBarDimens;
    }

    private int getProgressBarWidthDimen(){         // Used to check if 'mProgressBarDimens' array is set.
        if(mProgressBarDimens != null && mProgressBarDimens.length == SIZE_PROGRESS_BAR_DIMENS_ARRAY){
            return mProgressBarDimens[INDEX_PROGRESS_BAR_WIDTH];
        } else {
            return -0x1;
        }
    }

    private int getProgressBarHeightDimen(){
        return mProgressBarDimens[INDEX_PROGRESS_BAR_HEIGHT];
    }

    private int getNumLayers() {
        return mNumLayers;
    }

    private void setNumLayers(int numLayers) {
        this.mNumLayers = numLayers;
    }

    private int[][] getRotateDegrees() {
        return mRotateDegrees;
    }

    private void setRotateDegrees(int[][] rotateDegrees) {
        this.mRotateDegrees = rotateDegrees;
    }

    private int[] getShapes() {
        return mShapes;
    }

    private void setShapes(int[] shapes) {
        this.mShapes = shapes;
    }

    private int[] getInnerRadius() {
        return mInnerRadius;
    }

    private void setInnerRadius(int[] innerRadius) {
        this.mInnerRadius = innerRadius;
    }

    private int[] getThickness() {
        return mThickness;
    }

    private void setThickness(int[] thickness) {
        this.mThickness = thickness;
    }

    private int[][] getColorsMatrix() {
        return mColors;
    }

    private void setColorsMatrix(int[][] colorsMatrix) {
        this.mColors = colorsMatrix;
    }

    private int getProgressMsgColor() {
        return mProgressMsgColor;
    }

    private void setProgressMsgColor(int progressMsgColor) {
        this.mProgressMsgColor = progressMsgColor;
    }

    private int getProgressMsgDimen() {
        return mProgressMsgDimen;
    }

    private void setProgressMsgDimen(int progressMsgDimen) {
        this.mProgressMsgDimen = progressMsgDimen;
    }

    /** Public Methods **/
    private int[] getDegreesMatrixRow(int numRow){
        if(mRotateDegrees != null && mRotateDegrees.length > numRow) {
            return mRotateDegrees[numRow];
        } else {
            return new int[]{};
        }
    }

    private int getShape(int position){
        if(mShapes != null && mShapes.length > position){
            return mShapes[position];
        } else {
            return -0x1;
        }
    }

    private int getInnerRadius(int position){
        if(mInnerRadius != null && mInnerRadius.length > position){
            return mInnerRadius[position];
        } else {
            return -0x1;
        }
    }

    private int getThickness(int position){
        if(mThickness != null && mThickness.length > position){
            return mThickness[position];
        } else {
            return -0x1;
        }
    }

    private int[] getColorsMatrixRow(int numRow) {
        if(mColors != null && mColors.length > numRow){
            return mColors[numRow];
        } else {
            return new int[]{};
        }
    }

    /** Private Static Class Parcelable Creator **/
    private static class CreatorCustomLayoutBuilder implements Parcelable.Creator<CustomLayoutBuilder> {

        @Override
        public CustomLayoutBuilder createFromParcel(Parcel in) {
            return new CustomLayoutBuilder(in);
        }

        @Override
        public CustomLayoutBuilder[] newArray(int size) {
            return new CustomLayoutBuilder[size];
        }

    }

}
}
  • 该类有一个进度条,上面没有对话框和自定义文本。文本可以有 2 个动画:

  • Fade In -> Fade Out 动画:数字将从左到右依次淡出。在文本的末尾将从左侧重新开始。

  • 旋转动画:相同的顺序行为,但数字自己一个接一个地旋转而不是淡出。

  • 另一种方式是带有对话框的进度条(标题+消息)

旋转动画

对话框进度条

于 2019-05-23T13:08:20.040 回答