├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── Chandru_MacBook.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE.txt
├── MaterialCircleProgressBar.iml
├── MaterialProgress.iml
├── MaterialProgressBarCircle.iml
├── README.md
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── takeoffandroid
│ │ └── material
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── takeoffandroid
│ │ └── material
│ │ ├── CustomProgressDialog.java
│ │ ├── MainActivity.java
│ │ ├── MaterialProgressBar.java
│ │ └── MaterialProgressDrawable.java
│ └── res
│ ├── layout
│ └── view_material_progress.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | MaterialCircleProgressBar
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/Chandru_MacBook.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | Android
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 1.7
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Chandrasekar K
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so without any conditions and terms.
9 |
--------------------------------------------------------------------------------
/MaterialCircleProgressBar.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/MaterialProgress.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/MaterialProgressBarCircle.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://android-arsenal.com/details/1/1977)
2 |
3 |
4 |
5 | # MaterialCircleProgressBar
6 |
7 | MaterialCircleProgressBar is a custom implementation of ProgressBar dialog as similar to SwipeRefreshLayout loader. It could be used as an alternative for normal ProgressBar in android.
8 |
9 | 
10 |
11 | For tutorials, please visit my blog http://takeoffandroid.com/uncategorized/material-progress-dialog-using-v4-support-library/
12 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 21
5 | buildToolsVersion "21.1.2"
6 |
7 | defaultConfig {
8 | applicationId "com.takeoffandroid.material"
9 | minSdkVersion 11
10 | targetSdkVersion 21
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:22.0.0'
25 | }
26 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in F:\adt-bundle-windows-x86\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/takeoffandroid/material/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.takeoffandroid.material;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest () {
11 | super (Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/takeoffandroid/material/CustomProgressDialog.java:
--------------------------------------------------------------------------------
1 | package com.takeoffandroid.material;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 |
6 |
7 | public class CustomProgressDialog extends Dialog {
8 | MaterialProgressBar progress1;
9 |
10 | Context mContext;
11 | CustomProgressDialog dialog;
12 | public CustomProgressDialog(Context context) {
13 | super(context);
14 | this.mContext=context;
15 | }
16 | public CustomProgressDialog(Context context, int theme) {
17 | super(context, theme);
18 | }
19 |
20 | public CustomProgressDialog show(CharSequence message) {
21 |
22 | dialog = new CustomProgressDialog (mContext,R.style.ProgressDialog);
23 | dialog.setContentView(R.layout.view_material_progress);
24 |
25 | progress1 = (MaterialProgressBar) dialog.findViewById (R.id.progress1);
26 |
27 |
28 | progress1.setColorSchemeResources(R.color.red,R.color.green,R.color.blue,R.color.orange);
29 | dialog.setCancelable(true);
30 | if(dialog!= null) {
31 | dialog.show ();
32 | }
33 | return dialog;
34 | }
35 | public CustomProgressDialog dismiss(CharSequence message) {
36 | if(dialog!=null) {
37 | dialog.dismiss();
38 | }
39 |
40 | return dialog;
41 |
42 | }
43 |
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/takeoffandroid/material/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.takeoffandroid.material;
2 |
3 |
4 | import android.app.Activity;
5 | import android.os.Bundle;
6 |
7 |
8 |
9 | public class MainActivity extends Activity {
10 |
11 |
12 | private CustomProgressDialog mCustomProgressDialog;
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 |
18 | mCustomProgressDialog = new CustomProgressDialog(this);
19 | mCustomProgressDialog.show("");
20 |
21 | //Note:To stop progressdialog use mCustomProgressDialog.dismiss("");
22 |
23 |
24 | }
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/takeoffandroid/material/MaterialProgressBar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.takeoffandroid.material;
18 |
19 |
20 | import android.content.Context;
21 | import android.content.res.Resources;
22 | import android.content.res.TypedArray;
23 | import android.graphics.Canvas;
24 | import android.graphics.Color;
25 | import android.graphics.Paint;
26 | import android.graphics.RadialGradient;
27 | import android.graphics.Shader;
28 | import android.graphics.drawable.Drawable;
29 | import android.graphics.drawable.ShapeDrawable;
30 | import android.graphics.drawable.shapes.OvalShape;
31 | import android.net.Uri;
32 | import android.support.v4.view.ViewCompat;
33 | import android.util.AttributeSet;
34 | import android.view.animation.Animation;
35 | import android.widget.ImageView;
36 |
37 |
38 | public class MaterialProgressBar extends ImageView {
39 |
40 | private static final int KEY_SHADOW_COLOR = 0x1E000000;
41 | private static final int FILL_SHADOW_COLOR = 0x3D000000;
42 | // PX
43 | private static final float X_OFFSET = 0f;
44 | private static final float Y_OFFSET = 1.75f;
45 | private static final float SHADOW_RADIUS = 3.5f;
46 | private static final int SHADOW_ELEVATION = 4;
47 |
48 |
49 | private static final int DEFAULT_CIRCLE_BG_LIGHT = 0xFFFAFAFA;
50 | private static final int DEFAULT_CIRCLE_DIAMETER = 56;
51 | private static final int STROKE_WIDTH_LARGE = 3;
52 | public static final int DEFAULT_TEXT_SIZE = 9;
53 |
54 | private Animation.AnimationListener mListener;
55 | private int mShadowRadius;
56 | private int mBackGroundColor;
57 | private int mProgressColor;
58 | private int mProgressStokeWidth;
59 | private int mArrowWidth;
60 | private int mArrowHeight;
61 | private int mProgress;
62 | private int mMax;
63 | private int mDiameter;
64 | private int mInnerRadius;
65 | private Paint mTextPaint;
66 | private int mTextColor;
67 | private int mTextSize;
68 | private boolean mIfDrawText;
69 | private boolean mShowArrow;
70 | private MaterialProgressDrawable mProgressDrawable;
71 | private ShapeDrawable mBgCircle;
72 | private boolean mCircleBackgroundEnabled;
73 | private int[] mColors = new int[]{Color.BLACK};
74 |
75 | public MaterialProgressBar(Context context) {
76 | super(context);
77 | init(context, null, 0);
78 |
79 | }
80 |
81 | public MaterialProgressBar(Context context, AttributeSet attrs) {
82 | super(context, attrs);
83 | init(context, attrs, 0);
84 |
85 | }
86 |
87 | public MaterialProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
88 | super(context, attrs, defStyleAttr);
89 | init(context, attrs, defStyleAttr);
90 | }
91 | private void init(Context context, AttributeSet attrs, int defStyleAttr) {
92 | final TypedArray a = context.obtainStyledAttributes(
93 | attrs, R.styleable.MaterialProgressBar, defStyleAttr,0);
94 |
95 |
96 | final float density = getContext().getResources().getDisplayMetrics().density;
97 |
98 | mBackGroundColor = a.getColor(
99 | R.styleable.MaterialProgressBar_background_color, DEFAULT_CIRCLE_BG_LIGHT);
100 |
101 | mProgressColor = a.getColor(
102 | R.styleable.MaterialProgressBar_progress_color, DEFAULT_CIRCLE_BG_LIGHT);//ToDO 默认颜色
103 |
104 | mInnerRadius = a.getDimensionPixelOffset(
105 | R.styleable.MaterialProgressBar_inner_radius, -1);
106 |
107 | mProgressStokeWidth = a.getDimensionPixelOffset(
108 | R.styleable.MaterialProgressBar_progress_stoke_width, (int) (STROKE_WIDTH_LARGE*density));
109 | mArrowWidth = a.getDimensionPixelOffset(
110 | R.styleable.MaterialProgressBar_arrow_width, -1);
111 | mArrowHeight = a.getDimensionPixelOffset(
112 | R.styleable.MaterialProgressBar_arrow_height, -1);
113 | mTextSize = a.getDimensionPixelOffset(
114 | R.styleable.MaterialProgressBar_progress_text_size, (int)(DEFAULT_TEXT_SIZE *density));
115 | mTextColor = a.getColor(
116 | R.styleable.MaterialProgressBar_progress_text_color, Color.BLACK);
117 |
118 | mShowArrow = a.getBoolean(R.styleable.MaterialProgressBar_show_arrow,false);
119 | mCircleBackgroundEnabled = a.getBoolean(R.styleable.MaterialProgressBar_enable_circle_background,true);
120 |
121 |
122 |
123 | mProgress = a.getInt(R.styleable.MaterialProgressBar_progress, 0);
124 | mMax = a.getInt(R.styleable.MaterialProgressBar_max, 100);
125 | int textVisible = a.getInt(R.styleable.MaterialProgressBar_progress_text_visibility,1);
126 | if(textVisible != 1){
127 | mIfDrawText = true;
128 | }
129 |
130 | mTextPaint = new Paint();
131 | mTextPaint.setStyle(Paint.Style.FILL);
132 | mTextPaint.setColor(mTextColor);
133 | mTextPaint.setTextSize(mTextSize);
134 | mTextPaint.setAntiAlias(true);
135 | a.recycle();
136 | mProgressDrawable = new MaterialProgressDrawable(getContext(), this);
137 | super.setImageDrawable(mProgressDrawable);
138 | }
139 |
140 |
141 |
142 | private boolean elevationSupported() {
143 | return android.os.Build.VERSION.SDK_INT >= 21;
144 | }
145 |
146 | @Override
147 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
148 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
149 | if (!elevationSupported()) {
150 | setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2, getMeasuredHeight()
151 | + mShadowRadius * 2);
152 | }
153 | }
154 |
155 | @Override
156 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
157 | super.onLayout(changed, left, top, right, bottom);
158 | final float density = getContext().getResources().getDisplayMetrics().density;
159 | mDiameter = Math.min(getMeasuredWidth(),getMeasuredHeight());
160 | if(mDiameter <=0){
161 | mDiameter = (int)density*DEFAULT_CIRCLE_DIAMETER;
162 | }
163 | if(getBackground()==null&& mCircleBackgroundEnabled){
164 | final int shadowYOffset = (int) (density * Y_OFFSET);
165 | final int shadowXOffset = (int) (density * X_OFFSET);
166 | mShadowRadius = (int) (density * SHADOW_RADIUS);
167 |
168 |
169 | if (elevationSupported()) {
170 | mBgCircle = new ShapeDrawable(new OvalShape());
171 | ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
172 | } else {
173 | OvalShape oval = new OvalShadow(mShadowRadius, mDiameter);
174 | mBgCircle = new ShapeDrawable(oval);
175 | ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, mBgCircle.getPaint());
176 | mBgCircle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
177 | KEY_SHADOW_COLOR);
178 | final int padding = (int) mShadowRadius;
179 | // set padding so the inner image sits correctly within the shadow.
180 | setPadding(padding, padding, padding, padding);
181 | }
182 | mBgCircle.getPaint().setColor(mBackGroundColor);
183 | setBackgroundDrawable(mBgCircle);
184 | }
185 | mProgressDrawable.setBackgroundColor(mBackGroundColor);
186 | mProgressDrawable.setColorSchemeColors(mColors);
187 | mProgressDrawable.setSizeParameters(mDiameter, mDiameter,
188 | mInnerRadius <= 0 ? (mDiameter - mProgressStokeWidth * 2) / 4 : mInnerRadius,
189 | mProgressStokeWidth,
190 | mArrowWidth < 0 ? mProgressStokeWidth * 4 : mArrowWidth,
191 | mArrowHeight < 0 ? mProgressStokeWidth * 2 : mArrowHeight);
192 | if(isShowArrow()){
193 | mProgressDrawable.setArrowScale(1f);
194 | mProgressDrawable.showArrow(true);
195 | }
196 | super.setImageDrawable(null);
197 | super.setImageDrawable(mProgressDrawable);
198 | mProgressDrawable.setAlpha(255);
199 | mProgressDrawable.start();
200 | }
201 |
202 | @Override
203 | protected void onDraw(Canvas canvas) {
204 | super.onDraw(canvas);
205 | if(mIfDrawText) {
206 | String text = String.format("%s%%", mProgress);
207 | int x = getWidth() / 2 - text.length() * mTextSize / 4;
208 | int y = getHeight() / 2 + mTextSize / 4;
209 | canvas.drawText(text, x, y, mTextPaint);
210 | }
211 | }
212 |
213 | @Override
214 | final public void setImageResource(int resId) {
215 |
216 | }
217 |
218 |
219 |
220 | public boolean isShowArrow() {
221 | return mShowArrow;
222 | }
223 |
224 | public void setShowArrow(boolean showArrow) {
225 | this.mShowArrow = showArrow;
226 | }
227 |
228 |
229 | @Override
230 | final public void setImageURI(Uri uri) {
231 | super.setImageURI(uri);
232 | }
233 |
234 | @Override
235 | final public void setImageDrawable(Drawable drawable) {
236 | }
237 |
238 | public void setAnimationListener(Animation.AnimationListener listener) {
239 | mListener = listener;
240 | }
241 |
242 | @Override
243 | public void onAnimationStart() {
244 | super.onAnimationStart();
245 | if (mListener != null) {
246 | mListener.onAnimationStart(getAnimation());
247 | }
248 | }
249 |
250 | @Override
251 | public void onAnimationEnd() {
252 | super.onAnimationEnd();
253 | if (mListener != null) {
254 | mListener.onAnimationEnd(getAnimation());
255 | }
256 | }
257 |
258 |
259 | public void setColorSchemeResources(int... colorResIds) {
260 | final Resources res = getResources();
261 | int[] colorRes = new int[colorResIds.length];
262 | for (int i = 0; i < colorResIds.length; i++) {
263 | colorRes[i] = res.getColor(colorResIds[i]);
264 | }
265 | setColorSchemeColors(colorRes);
266 | }
267 |
268 |
269 | public void setColorSchemeColors(int... colors) {
270 | mColors = colors;
271 | if(mProgressDrawable!=null) {
272 | mProgressDrawable.setColorSchemeColors(colors);
273 | }
274 | }
275 |
276 | public void setBackgroundColor(int colorRes) {
277 | if (getBackground() instanceof ShapeDrawable) {
278 | final Resources res = getResources();
279 | ((ShapeDrawable) getBackground()).getPaint().setColor(res.getColor(colorRes));
280 | }
281 | }
282 |
283 | public boolean isShowProgressText() {
284 | return mIfDrawText;
285 | }
286 |
287 | public void setShowProgressText(boolean mIfDrawText) {
288 | this.mIfDrawText = mIfDrawText;
289 | }
290 |
291 | public int getMax() {
292 | return mMax;
293 | }
294 |
295 | public void setMax(int max) {
296 | mMax = max;
297 | }
298 |
299 | public int getProgress() {
300 | return mProgress;
301 | }
302 |
303 | public void setProgress(int progress) {
304 | if (getMax() > 0) {
305 | mProgress = progress;
306 | }
307 | }
308 |
309 |
310 | public boolean circleBackgroundEnabled() {
311 | return mCircleBackgroundEnabled;
312 | }
313 |
314 | public void setCircleBackgroundEnabled(boolean enableCircleBackground) {
315 | this.mCircleBackgroundEnabled = enableCircleBackground;
316 | }
317 |
318 |
319 | @Override
320 | public int getVisibility() {
321 | return super.getVisibility();
322 | }
323 |
324 | @Override
325 | public void setVisibility(int visibility) {
326 | super.setVisibility(visibility);
327 | if (mProgressDrawable != null) {
328 | if(visibility!=VISIBLE) {
329 | mProgressDrawable.stop();
330 | }
331 | mProgressDrawable.setVisible(visibility == VISIBLE, false);
332 | }
333 | }
334 |
335 | @Override
336 | protected void onAttachedToWindow() {
337 | super.onAttachedToWindow();
338 | if (mProgressDrawable != null) {
339 | mProgressDrawable.stop();
340 | mProgressDrawable.setVisible(getVisibility() == VISIBLE, false);
341 | }
342 | }
343 |
344 | @Override
345 | protected void onDetachedFromWindow() {
346 | super.onDetachedFromWindow();
347 | if (mProgressDrawable != null) {
348 | mProgressDrawable.stop();
349 | mProgressDrawable.setVisible(false, false);
350 | }
351 | }
352 |
353 |
354 | private class OvalShadow extends OvalShape {
355 | private RadialGradient mRadialGradient;
356 | private int mShadowRadius;
357 | private Paint mShadowPaint;
358 | private int mCircleDiameter;
359 |
360 | public OvalShadow(int shadowRadius, int circleDiameter) {
361 | super();
362 | mShadowPaint = new Paint();
363 | mShadowRadius = shadowRadius;
364 | mCircleDiameter = circleDiameter;
365 | mRadialGradient = new RadialGradient(mCircleDiameter / 2, mCircleDiameter / 2,
366 | mShadowRadius, new int[] {
367 | FILL_SHADOW_COLOR, Color.TRANSPARENT
368 | }, null, Shader.TileMode.CLAMP);
369 | mShadowPaint.setShader(mRadialGradient);
370 | }
371 |
372 | @Override
373 | public void draw(Canvas canvas, Paint paint) {
374 | final int viewWidth = MaterialProgressBar.this.getWidth();
375 | final int viewHeight = MaterialProgressBar.this.getHeight();
376 | canvas.drawCircle(viewWidth / 2, viewHeight / 2, (mCircleDiameter / 2 + mShadowRadius),
377 | mShadowPaint);
378 | canvas.drawCircle(viewWidth / 2, viewHeight / 2, (mCircleDiameter / 2), paint);
379 | }
380 | }
381 | }
382 |
--------------------------------------------------------------------------------
/app/src/main/java/com/takeoffandroid/material/MaterialProgressDrawable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.takeoffandroid.material;
18 |
19 | import android.content.Context;
20 | import android.content.res.Resources;
21 | import android.graphics.Canvas;
22 | import android.graphics.Color;
23 | import android.graphics.ColorFilter;
24 | import android.graphics.Paint;
25 | import android.graphics.Paint.Style;
26 | import android.graphics.Path;
27 | import android.graphics.PixelFormat;
28 | import android.graphics.Rect;
29 | import android.graphics.RectF;
30 | import android.graphics.drawable.Animatable;
31 | import android.graphics.drawable.Drawable;
32 | import android.support.annotation.IntDef;
33 | import android.support.annotation.NonNull;
34 | import android.util.DisplayMetrics;
35 | import android.util.Log;
36 | import android.view.View;
37 | import android.view.animation.AccelerateDecelerateInterpolator;
38 | import android.view.animation.Animation;
39 | import android.view.animation.Interpolator;
40 | import android.view.animation.LinearInterpolator;
41 | import android.view.animation.Transformation;
42 |
43 | import java.lang.annotation.Retention;
44 | import java.lang.annotation.RetentionPolicy;
45 | import java.util.ArrayList;
46 |
47 | /**
48 | * Fancy progress indicator for Material theme.
49 | *
50 | * @hide
51 | */
52 | public class MaterialProgressDrawable extends Drawable implements Animatable {
53 | // Maps to ProgressBar.Large style
54 | public static final int LARGE = 0;
55 | // Maps to ProgressBar default style
56 | public static final int DEFAULT = 1;
57 | private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
58 | private static final Interpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator();
59 | private static final Interpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator();
60 | private static final Interpolator EASE_INTERPOLATOR = new AccelerateDecelerateInterpolator();
61 | // Maps to ProgressBar default style
62 | private static final int CIRCLE_DIAMETER = 40;
63 | private static final float CENTER_RADIUS = 8.75f; //should add up to 10 when + stroke_width
64 | private static final float STROKE_WIDTH = 2.5f;
65 | // Maps to ProgressBar.Large style
66 | private static final int CIRCLE_DIAMETER_LARGE = 56;
67 | private static final float CENTER_RADIUS_LARGE = 12.5f;
68 | static final float STROKE_WIDTH_LARGE = 3f;
69 | /**
70 | * The duration of a single progress spin in milliseconds.
71 | */
72 | private static final int ANIMATION_DURATION = 1000 * 80 / 60;
73 | /**
74 | * The number of points in the progress "star".
75 | */
76 | private static final float NUM_POINTS = 5f;
77 | /**
78 | * Layout info for the arrowhead in dp
79 | */
80 | private static final int ARROW_WIDTH = 10;
81 | private static final int ARROW_HEIGHT = 5;
82 | private static final float ARROW_OFFSET_ANGLE = 0;
83 | /**
84 | * Layout info for the arrowhead for the large spinner in dp
85 | */
86 | static final int ARROW_WIDTH_LARGE = 12;
87 | static final int ARROW_HEIGHT_LARGE = 6;
88 | private static final float MAX_PROGRESS_ARC = .8f;
89 | private final int[] COLORS = new int[]{
90 | Color.BLACK
91 | };
92 | /**
93 | * The list of animators operating on this drawable.
94 | */
95 | private final ArrayList mAnimators = new ArrayList();
96 | /**
97 | * The indicator ring, used to manage animation state.
98 | */
99 | private final Ring mRing;
100 | private final Callback mCallback = new Callback() {
101 | @Override
102 | public void invalidateDrawable(Drawable d) {
103 | invalidateSelf();
104 | }
105 |
106 | @Override
107 | public void scheduleDrawable(Drawable d, Runnable what, long when) {
108 | scheduleSelf(what, when);
109 | }
110 |
111 | @Override
112 | public void unscheduleDrawable(Drawable d, Runnable what) {
113 | unscheduleSelf(what);
114 | }
115 | };
116 | boolean mFinishing;
117 | /**
118 | * Canvas rotation in degrees.
119 | */
120 | private float mRotation;
121 | private Resources mResources;
122 | private View mAnimExcutor;
123 | private Animation mAnimation;
124 | private float mRotationCount;
125 | private double mWidth;
126 | private double mHeight;
127 |
128 | public MaterialProgressDrawable(Context context, View animExcutor) {
129 | mAnimExcutor = animExcutor;
130 | mResources = context.getResources();
131 |
132 | mRing = new Ring(mCallback);
133 | mRing.setColors(COLORS);
134 |
135 | updateSizes(DEFAULT);
136 | setupAnimators();
137 | }
138 |
139 | public void setSizeParameters(double progressCircleWidth, double progressCircleHeight,
140 | double centerRadius, double strokeWidth, float arrowWidth, float arrowHeight) {
141 | final Ring ring = mRing;
142 | mWidth = progressCircleWidth;
143 | mHeight = progressCircleHeight ;
144 | ring.setStrokeWidth((float) strokeWidth );
145 | ring.setCenterRadius(centerRadius);
146 | ring.setColorIndex(0);
147 | ring.setArrowDimensions(arrowWidth , arrowHeight );
148 | ring.setInsets((int) mWidth, (int) mHeight);
149 | }
150 |
151 | /**
152 | * Set the overall size for the progress spinner. This updates the radius
153 | * and stroke width of the ring.
154 | *
155 | * @param size One of {@link com.takeoffandroid.material.MaterialProgressDrawable.LARGE} or
156 | * {@link com.takeoffandroid.material.MaterialProgressDrawable.DEFAULT}
157 | */
158 | public void updateSizes(@ProgressDrawableSize int size) {
159 | final DisplayMetrics metrics = mResources.getDisplayMetrics();
160 | final float screenDensity = metrics.density;
161 |
162 | if (size == LARGE) {
163 | setSizeParameters(CIRCLE_DIAMETER_LARGE*screenDensity, CIRCLE_DIAMETER_LARGE*screenDensity, CENTER_RADIUS_LARGE*screenDensity,
164 | STROKE_WIDTH_LARGE*screenDensity, ARROW_WIDTH_LARGE*screenDensity, ARROW_HEIGHT_LARGE*screenDensity);
165 | } else {
166 | setSizeParameters(CIRCLE_DIAMETER*screenDensity, CIRCLE_DIAMETER*screenDensity, CENTER_RADIUS*screenDensity, STROKE_WIDTH*screenDensity,
167 | ARROW_WIDTH*screenDensity, ARROW_HEIGHT*screenDensity);
168 | }
169 | }
170 |
171 | /**
172 | * @param show Set to true to display the arrowhead on the progress spinner.
173 | */
174 | public void showArrow(boolean show) {
175 | mRing.setShowArrow(show);
176 | }
177 |
178 | /**
179 | * @param scale Set the scale of the arrowhead for the spinner.
180 | */
181 | public void setArrowScale(float scale) {
182 | mRing.setArrowScale(scale);
183 | }
184 |
185 | /**
186 | * Set the start and end trim for the progress spinner arc.
187 | *
188 | * @param startAngle start angle
189 | * @param endAngle end angle
190 | */
191 | public void setStartEndTrim(float startAngle, float endAngle) {
192 | mRing.setStartTrim(startAngle);
193 | mRing.setEndTrim(endAngle);
194 | }
195 |
196 | /**
197 | * Set the amount of rotation to apply to the progress spinner.
198 | *
199 | * @param rotation Rotation is from [0..1]
200 | */
201 | public void setProgressRotation(float rotation) {
202 | mRing.setRotation(rotation);
203 | }
204 |
205 | /**
206 | * Update the background color of the circle image view.
207 | */
208 | public void setBackgroundColor(int color) {
209 | mRing.setBackgroundColor(color);
210 | }
211 |
212 | /**
213 | * Set the colors used in the progress animation from color resources.
214 | * The first color will also be the color of the bar that grows in response
215 | * to a user swipe gesture.
216 | *
217 | * @param colors
218 | */
219 | public void setColorSchemeColors(int... colors) {
220 | mRing.setColors(colors);
221 | mRing.setColorIndex(0);
222 | }
223 |
224 | @Override
225 | public int getIntrinsicHeight() {
226 | return (int) mHeight;
227 | }
228 |
229 | @Override
230 | public int getIntrinsicWidth() {
231 | return (int) mWidth;
232 | }
233 |
234 | @Override
235 | public void draw(Canvas c) {
236 | final Rect bounds = getBounds();
237 | final int saveCount = c.save();
238 | c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY());
239 | mRing.draw(c, bounds);
240 | c.restoreToCount(saveCount);
241 | }
242 |
243 | public int getAlpha() {
244 | return mRing.getAlpha();
245 | }
246 |
247 | @Override
248 | public void setAlpha(int alpha) {
249 | mRing.setAlpha(alpha);
250 | }
251 |
252 | @Override
253 | public void setColorFilter(ColorFilter colorFilter) {
254 | mRing.setColorFilter(colorFilter);
255 | }
256 |
257 | @SuppressWarnings("unused")
258 | private float getRotation() {
259 | return mRotation;
260 | }
261 |
262 | @SuppressWarnings("unused")
263 | void setRotation(float rotation) {
264 | mRotation = rotation;
265 | invalidateSelf();
266 | }
267 |
268 | @Override
269 | public int getOpacity() {
270 | return PixelFormat.TRANSLUCENT;
271 | }
272 |
273 | @Override
274 | public boolean isRunning() {
275 | final ArrayList animators = mAnimators;
276 | final int N = animators.size();
277 | for (int i = 0; i < N; i++) {
278 | final Animation animator = animators.get(i);
279 | if (animator.hasStarted() && !animator.hasEnded()) {
280 | return true;
281 | }
282 | }
283 | return false;
284 | }
285 |
286 | @Override
287 | public void start() {
288 | mAnimation.reset();
289 | mRing.storeOriginals();
290 | // Already showing some part of the ring
291 | if (mRing.getEndTrim() != mRing.getStartTrim()) {
292 | mFinishing = true;
293 | mAnimation.setDuration(ANIMATION_DURATION / 2);
294 | mAnimExcutor.startAnimation(mAnimation);
295 | } else {
296 | mRing.setColorIndex(0);
297 | mRing.resetOriginals();
298 | mAnimation.setDuration(ANIMATION_DURATION);
299 | mAnimExcutor.startAnimation(mAnimation);
300 | }
301 | }
302 |
303 | @Override
304 | public void stop() {
305 | mAnimExcutor.clearAnimation();
306 | setRotation(0);
307 | mRing.setShowArrow(false);
308 | mRing.setColorIndex(0);
309 | mRing.resetOriginals();
310 | }
311 |
312 | private void applyFinishTranslation(float interpolatedTime, Ring ring) {
313 | // shrink back down and complete a full rotation before
314 | // starting other circles
315 | // Rotation goes between [0..1].
316 | float targetRotation = (float) (Math.floor(ring.getStartingRotation() / MAX_PROGRESS_ARC)
317 | + 1f);
318 | final float startTrim = ring.getStartingStartTrim()
319 | + (ring.getStartingEndTrim() - ring.getStartingStartTrim()) * interpolatedTime;
320 | ring.setStartTrim(startTrim);
321 | final float rotation = ring.getStartingRotation()
322 | + ((targetRotation - ring.getStartingRotation()) * interpolatedTime);
323 | ring.setRotation(rotation);
324 | }
325 |
326 | private void setupAnimators() {
327 | final Ring ring = mRing;
328 | final Animation animation = new Animation() {
329 | @Override
330 | public void applyTransformation(float interpolatedTime, Transformation t) {
331 | if (mFinishing) {
332 | applyFinishTranslation(interpolatedTime, ring);
333 | } else {
334 | // The minProgressArc is calculated from 0 to create an
335 | // angle that
336 | // matches the stroke width.
337 | final float minProgressArc = (float) Math.toRadians(
338 | ring.getStrokeWidth() / (2 * Math.PI * ring.getCenterRadius()));
339 | final float startingEndTrim = ring.getStartingEndTrim();
340 | final float startingTrim = ring.getStartingStartTrim();
341 | final float startingRotation = ring.getStartingRotation();
342 |
343 | // Offset the minProgressArc to where the endTrim is
344 | // located.
345 | final float minArc = MAX_PROGRESS_ARC - minProgressArc;
346 | float endTrim = startingEndTrim + (minArc
347 | * START_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));
348 | float startTrim = startingTrim + (MAX_PROGRESS_ARC
349 | * END_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));
350 |
351 | final float sweepTrim = endTrim-startTrim;
352 | //Avoid the ring to be a full circle
353 | if(Math.abs(sweepTrim)>=1){
354 | endTrim = startTrim+0.5f;
355 | }
356 |
357 | ring.setEndTrim(endTrim);
358 |
359 | ring.setStartTrim(startTrim);
360 |
361 | final float rotation = startingRotation + (0.25f * interpolatedTime);
362 | ring.setRotation(rotation);
363 |
364 | float groupRotation = ((720.0f / NUM_POINTS) * interpolatedTime)
365 | + (720.0f * (mRotationCount / NUM_POINTS));
366 | setRotation(groupRotation);
367 | }
368 | }
369 | };
370 | animation.setRepeatCount(Animation.INFINITE);
371 | animation.setRepeatMode(Animation.RESTART);
372 | animation.setInterpolator(LINEAR_INTERPOLATOR);
373 | animation.setAnimationListener(new Animation.AnimationListener() {
374 |
375 | @Override
376 | public void onAnimationStart(Animation animation) {
377 | mRotationCount = 0;
378 | }
379 |
380 | @Override
381 | public void onAnimationEnd(Animation animation) {
382 | // do nothing
383 | }
384 |
385 | @Override
386 | public void onAnimationRepeat(Animation animation) {
387 | ring.storeOriginals();
388 | ring.goToNextColor();
389 | ring.setStartTrim(ring.getEndTrim());
390 | if (mFinishing) {
391 | // finished closing the last ring from the swipe gesture; go
392 | // into progress mode
393 | mFinishing = false;
394 | animation.setDuration(ANIMATION_DURATION);
395 | ring.setShowArrow(false);
396 | } else {
397 | mRotationCount = (mRotationCount + 1) % (NUM_POINTS);
398 | }
399 | }
400 | });
401 | mAnimation = animation;
402 | }
403 |
404 | @Retention(RetentionPolicy.CLASS)
405 | @IntDef({LARGE, DEFAULT})
406 | public @interface ProgressDrawableSize {
407 | }
408 |
409 | private static class Ring {
410 | private final RectF mTempBounds = new RectF();
411 | private final Paint mPaint = new Paint();
412 | private final Paint mArrowPaint = new Paint();
413 |
414 | private final Callback mCallback;
415 | private final Paint mCirclePaint = new Paint();
416 | private float mStartTrim = 0.0f;
417 | private float mEndTrim = 0.0f;
418 | private float mRotation = 0.0f;
419 | private float mStrokeWidth = 5.0f;
420 | private float mStrokeInset = 2.5f;
421 | private int[] mColors;
422 | // mColorIndex represents the offset into the available mColors that the
423 | // progress circle should currently display. As the progress circle is
424 | // animating, the mColorIndex moves by one to the next available color.
425 | private int mColorIndex;
426 | private float mStartingStartTrim;
427 | private float mStartingEndTrim;
428 | private float mStartingRotation;
429 | private boolean mShowArrow;
430 | private Path mArrow;
431 | private float mArrowScale;
432 | private double mRingCenterRadius;
433 | private int mArrowWidth;
434 | private int mArrowHeight;
435 | private int mAlpha;
436 | private int mBackgroundColor;
437 |
438 | public Ring(Callback callback) {
439 | mCallback = callback;
440 |
441 | mPaint.setStrokeCap(Paint.Cap.SQUARE);
442 | mPaint.setAntiAlias(true);
443 | mPaint.setStyle(Style.STROKE);
444 |
445 | mArrowPaint.setStyle(Style.FILL);
446 | mArrowPaint.setAntiAlias(true);
447 | }
448 |
449 | public void setBackgroundColor(int color) {
450 | mBackgroundColor = color;
451 | }
452 |
453 | /**
454 | * Set the dimensions of the arrowhead.
455 | *
456 | * @param width Width of the hypotenuse of the arrow head
457 | * @param height Height of the arrow point
458 | */
459 | public void setArrowDimensions(float width, float height) {
460 | mArrowWidth = (int) width;
461 | mArrowHeight = (int) height;
462 | }
463 |
464 | /**
465 | * Draw the progress spinner
466 | */
467 | public void draw(Canvas c, Rect bounds) {
468 | final RectF arcBounds = mTempBounds;
469 | arcBounds.set(bounds);
470 | arcBounds.inset(mStrokeInset, mStrokeInset);
471 |
472 | final float startAngle = (mStartTrim + mRotation) * 360;
473 | final float endAngle = (mEndTrim + mRotation) * 360;
474 | float sweepAngle = endAngle - startAngle;
475 | mPaint.setColor(mColors[mColorIndex]);
476 | c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);
477 |
478 | drawTriangle(c, startAngle, sweepAngle, bounds);
479 |
480 | if (mAlpha < 255) {
481 | mCirclePaint.setColor(mBackgroundColor);
482 | mCirclePaint.setAlpha(255 - mAlpha);
483 | c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2,
484 | mCirclePaint);
485 | }
486 | }
487 |
488 | private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) {
489 | if (mShowArrow) {
490 | if (mArrow == null) {
491 | mArrow = new Path();
492 | mArrow.setFillType(Path.FillType.EVEN_ODD);
493 | } else {
494 | mArrow.reset();
495 | }
496 |
497 | // Adjust the position of the triangle so that it is inset as
498 | // much as the arc, but also centered on the arc.
499 | float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX());
500 | float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY());
501 |
502 | // Update the path each time. This works around an issue in SKIA
503 | // where concatenating a rotation matrix to a scale matrix
504 | // ignored a starting negative rotation. This appears to have
505 | // been fixed as of API 21.
506 | mArrow.moveTo(0, 0);
507 | mArrow.lineTo((mArrowWidth) * mArrowScale, 0);
508 | mArrow.lineTo(((mArrowWidth) * mArrowScale / 2), (mArrowHeight
509 | * mArrowScale));
510 | mArrow.offset(x-((mArrowWidth) * mArrowScale / 2), y);
511 | mArrow.close();
512 | // draw a triangle
513 | mArrowPaint.setColor(mColors[mColorIndex]);
514 | //when sweepAngle < 0 adjust the position of the arrow
515 | c.rotate(startAngle + (sweepAngle<0?0:sweepAngle) - ARROW_OFFSET_ANGLE, bounds.exactCenterX(),
516 | bounds.exactCenterY());
517 | c.drawPath(mArrow, mArrowPaint);
518 | }
519 | }
520 |
521 | /**
522 | * Set the colors the progress spinner alternates between.
523 | *
524 | * @param colors Array of integers describing the colors. Must be non-null
.
525 | */
526 | public void setColors(@NonNull int[] colors) {
527 | mColors = colors;
528 | // if colors are reset, make sure to reset the color index as well
529 | setColorIndex(0);
530 | }
531 |
532 | /**
533 | * @param index Index into the color array of the color to display in
534 | * the progress spinner.
535 | */
536 | public void setColorIndex(int index) {
537 | mColorIndex = index;
538 | }
539 |
540 | /**
541 | * Proceed to the next available ring color. This will automatically
542 | * wrap back to the beginning of colors.
543 | */
544 | public void goToNextColor() {
545 | mColorIndex = (mColorIndex + 1) % (mColors.length);
546 | }
547 |
548 | public void setColorFilter(ColorFilter filter) {
549 | mPaint.setColorFilter(filter);
550 | invalidateSelf();
551 | }
552 |
553 | /**
554 | * @return Current alpha of the progress spinner and arrowhead.
555 | */
556 | public int getAlpha() {
557 | return mAlpha;
558 | }
559 |
560 | /**
561 | * @param alpha Set the alpha of the progress spinner and associated arrowhead.
562 | */
563 | public void setAlpha(int alpha) {
564 | mAlpha = alpha;
565 | }
566 |
567 | @SuppressWarnings("unused")
568 | public float getStrokeWidth() {
569 | return mStrokeWidth;
570 | }
571 |
572 | /**
573 | * @param strokeWidth Set the stroke width of the progress spinner in pixels.
574 | */
575 | public void setStrokeWidth(float strokeWidth) {
576 | mStrokeWidth = strokeWidth;
577 | mPaint.setStrokeWidth(strokeWidth);
578 | invalidateSelf();
579 | }
580 |
581 | @SuppressWarnings("unused")
582 | public float getStartTrim() {
583 | return mStartTrim;
584 | }
585 |
586 | @SuppressWarnings("unused")
587 | public void setStartTrim(float startTrim) {
588 | mStartTrim = startTrim;
589 | invalidateSelf();
590 | }
591 |
592 | public float getStartingStartTrim() {
593 | return mStartingStartTrim;
594 | }
595 |
596 | public float getStartingEndTrim() {
597 | return mStartingEndTrim;
598 | }
599 |
600 | @SuppressWarnings("unused")
601 | public float getEndTrim() {
602 | return mEndTrim;
603 | }
604 |
605 | @SuppressWarnings("unused")
606 | public void setEndTrim(float endTrim) {
607 | mEndTrim = endTrim;
608 | invalidateSelf();
609 | }
610 |
611 | @SuppressWarnings("unused")
612 | public float getRotation() {
613 | return mRotation;
614 | }
615 |
616 | @SuppressWarnings("unused")
617 | public void setRotation(float rotation) {
618 | mRotation = rotation;
619 | invalidateSelf();
620 | }
621 |
622 | public void setInsets(int width, int height) {
623 | final float minEdge = (float) Math.min(width, height);
624 | float insets;
625 | if (mRingCenterRadius <= 0 || minEdge < 0) {
626 | insets = (float) Math.ceil(mStrokeWidth / 2.0f);
627 | } else {
628 | insets = (float) (minEdge / 2.0f - mRingCenterRadius);
629 | }
630 | mStrokeInset = insets;
631 | }
632 |
633 | @SuppressWarnings("unused")
634 | public float getInsets() {
635 | return mStrokeInset;
636 | }
637 |
638 | public double getCenterRadius() {
639 | return mRingCenterRadius;
640 | }
641 |
642 | /**
643 | * @param centerRadius Inner radius in px of the circle the progress
644 | * spinner arc traces.
645 | */
646 | public void setCenterRadius(double centerRadius) {
647 | mRingCenterRadius = centerRadius;
648 | }
649 |
650 | /**
651 | * @param show Set to true to show the arrow head on the progress spinner.
652 | */
653 | public void setShowArrow(boolean show) {
654 | if (mShowArrow != show) {
655 | mShowArrow = show;
656 | invalidateSelf();
657 | }
658 | }
659 |
660 | /**
661 | * @param scale Set the scale of the arrowhead for the spinner.
662 | */
663 | public void setArrowScale(float scale) {
664 | if (scale != mArrowScale) {
665 | mArrowScale = scale;
666 | invalidateSelf();
667 | }
668 | }
669 |
670 | /**
671 | * @return The amount the progress spinner is currently rotated, between [0..1].
672 | */
673 | public float getStartingRotation() {
674 | return mStartingRotation;
675 | }
676 |
677 | /**
678 | * If the start / end trim are offset to begin with, store them so that
679 | * animation starts from that offset.
680 | */
681 | public void storeOriginals() {
682 | mStartingStartTrim = mStartTrim;
683 | mStartingEndTrim = mEndTrim;
684 | mStartingRotation = mRotation;
685 | }
686 |
687 | /**
688 | * Reset the progress spinner to default rotation, start and end angles.
689 | */
690 | public void resetOriginals() {
691 | mStartingStartTrim = 0;
692 | mStartingEndTrim = 0;
693 | mStartingRotation = 0;
694 | setStartTrim(0);
695 | setEndTrim(0);
696 | setRotation(0);
697 | }
698 |
699 | private void invalidateSelf() {
700 | mCallback.invalidateDrawable(null);
701 | }
702 | }
703 |
704 | /**
705 | * Squishes the interpolation curve into the second half of the animation.
706 | */
707 | private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator {
708 | @Override
709 | public float getInterpolation(float input) {
710 | return super.getInterpolation(Math.max(0, (input - 0.5f) * 2.0f));
711 | }
712 | }
713 |
714 | /**
715 | * Squishes the interpolation curve into the first half of the animation.
716 | */
717 | private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator {
718 | @Override
719 | public float getInterpolation(float input) {
720 | return super.getInterpolation(Math.min(1, input * 2.0f));
721 | }
722 | }
723 | }
724 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_material_progress.xml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ckdevrel/MaterialCircleProgressBar/92cc2f308045befd9cdd5b4a636d6090fd1883fe/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ckdevrel/MaterialCircleProgressBar/92cc2f308045befd9cdd5b4a636d6090fd1883fe/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ckdevrel/MaterialCircleProgressBar/92cc2f308045befd9cdd5b4a636d6090fd1883fe/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ckdevrel/MaterialCircleProgressBar/92cc2f308045befd9cdd5b4a636d6090fd1883fe/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #990000
4 | #009900
5 | #000099
6 | #FF9900
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MaterialProgress
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.1.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ckdevrel/MaterialCircleProgressBar/92cc2f308045befd9cdd5b4a636d6090fd1883fe/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------