Skip to content

Commit

Permalink
improved progress drawable, updated readme
Browse files Browse the repository at this point in the history
  • Loading branch information
bleeding182 committed Jan 5, 2016
1 parent c624550 commit 1cdec64
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 115 deletions.
8 changes: 7 additions & 1 deletion SpinningStar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

This project provides a sample of how to add an animated custom drawable to a toolbar.

A full guide explaining how to use and animate custom drawables can be found here: [Custom Drawables and Animations](http://bleeding182.blogspot.co.at/2016/01/custom-drawables-and-animations.html)

![Anticipate Overshoot](anticipateOvershoot.gif)

For the code take a look at [SpinningStarDrawable](/blob/master/SpinningStar/app/src/main/java/at/bleeding182/samples/spinningstar/SpinningStarDrawable.java)

This sample also features a proof of concept for an ideterminate rectangular progress bar.
## Indeterminate progress bar drawable

This sample also features a proof of concept for an indeterminate rectangular progress bar. This was used as a proof of concept for [Modifying the resource image of Progress Bar](http://stackoverflow.com/questions/34536075/modifying-the-resource-image-of-progress-bar)

![Progress drawables](indeterminateProgressBars.gif)
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ protected void onCreate(Bundle savedInstanceState) {
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress);
progressBar.setIndeterminateDrawable(new RectProgressDrawable());
progressBar.setIndeterminate(true);


RectProgressDrawable drawable = new RectProgressDrawable();
drawable.setPoints(7);
ProgressBar progressBar2 = (ProgressBar) findViewById(R.id.progress2);
progressBar2.setIndeterminateDrawable(drawable);
progressBar2.setIndeterminate(true);

drawable = new RectProgressDrawable();
drawable.setPoints(10);
drawable.setAnimatedPoints(20);
ProgressBar progressBar3 = (ProgressBar) findViewById(R.id.progress3);
progressBar3.setIndeterminateDrawable(drawable);
progressBar3.setIndeterminate(true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,135 +8,175 @@
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.Log;

/**
* @author David Medenjak on 24.12.2015.
*
* Proof of concept for http://stackoverflow.com/questions/34536075/modifying-the-resource-image-of-progress-bar/34590765#34590765
* <p/>
* Proof of concept for http://stackoverflow.com/questions/34536075/modifying-the-resource-image-of-progress-bar/34590765#34590765
*/
public class RectProgressDrawable extends Drawable implements Runnable, Animatable {
private static final long FRAME_DELAY = 1000 / 60;
private boolean mRunning = false;
private long mStartTime;
private int mDuration = 1000;

private Paint mPaint;

private float[] posX = new float[16];
private float[] posY = new float[16];
private float mSize;

private void init() {
if (mPaint == null) {
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
public class RectProgressDrawable extends Drawable implements Runnable, Animatable {
private static final long FRAME_DELAY = 1000 / 60;
private static final String TAG = "RectProgressDrawable";
private boolean mRunning = false;
private long mStartTime;
private int mDuration = 1000;

private Paint mPaint;

private float[] posX;
private float[] posY;
private float mSize;
private int mPoints = 5;

/**
* The padding in px.
*/
private int mPadding = 4;
private int mAnimatedPoints = 5;

public void setPoints(int points) {
if (points != mPoints) {
mPoints = points;
init();
}
}
Rect bounds = getBounds();
float cellWidth = ((float) bounds.width()) / 5f;
float cellHeight = ((float) bounds.height()) / 5f;

float min = Math.min(cellWidth, cellHeight);
mSize = (min * 0.9f) / 4;
private void init() {
if (mPaint == null) {
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
}

for (int i = 0; i < 5; i++) { // top row
posX[i] = bounds.left + cellWidth * (float) i + cellWidth / 2;
posY[i] = cellHeight / 2;
}
for (int i = 0; i < 3; i++) { // sides
// right side top bottom
posX[5 + i] = cellWidth * 4 + cellWidth / 2;
posY[5 + i] = cellHeight * (i + 1) + cellHeight / 2;
//left side bottom top
posX[13 + i] = cellWidth / 2;
posY[13 + i] = cellHeight * (3 - i) + cellHeight / 2;
}
for (int i = 0; i < 5; i++) { // bottom from right to left
posX[8 + i] = cellWidth * (4 - i) + cellWidth / 2;
posY[8 + i] = cellHeight * 4 + cellHeight / 2;
posX = new float[(mPoints - 1) * 4];
posY = new float[(mPoints - 1) * 4];

Rect bounds = new Rect();
bounds.set(getBounds());
bounds.inset(mPadding, mPadding);

float cellWidth = ((float) bounds.width()) / ((float) mPoints);
float cellHeight = ((float) bounds.height()) / ((float) mPoints);

float min = Math.min(cellWidth, cellHeight);
mSize = min / (mPoints - 1);

for (int i = 0; i < mPoints; i++) { // top row
posX[i] = bounds.left + cellWidth * (float) i + cellWidth / 2;
posY[i] = bounds.top + cellHeight / 2;
}
for (int i = 0; i < mPoints - 2; i++) { // sides
// right side top bottom
posX[mPoints + i] = bounds.left + cellWidth * (mPoints - 1) + cellWidth / 2;
posY[mPoints + i] = bounds.top + cellHeight * (i + 1) + cellHeight / 2;
//left side bottom top
posX[3 * mPoints - 2 + i] = bounds.left + cellWidth / 2;
posY[3 * mPoints - 2 + i] = bounds.top + cellHeight * (mPoints - 2 - i) + cellHeight / 2;
}
for (int i = 0; i < mPoints; i++) { // bottom from right to left
posX[2 * mPoints - 2 + i] = bounds.left + cellWidth * (mPoints - 1 - i) + cellWidth / 2;
posY[2 * mPoints - 2 + i] = bounds.top + cellHeight * (mPoints - 1) + cellHeight / 2;
}
}
}

@Override
public void draw(Canvas canvas) {
final Rect bounds = getBounds();
@Override
public void draw(Canvas canvas) {
if (isRunning()) {
// animation in progress
final int save = canvas.save();

if (isRunning()) {
// animation in progress
final int save = canvas.save();
for (int i = 0; i < 16; i++) {
long timeDiff = SystemClock.uptimeMillis() - mStartTime;
float progress = ((float) timeDiff) / ((float) mDuration) * 16;
int level = ((int) (progress + 0.5)) % 16;
if (i >= level && i < level + 5) {
float num = i - level; // 0..5
float size = mSize * (1 + (num * 0.2f));
canvas.drawCircle(posX[i], posY[i], size, mPaint);
} else {

float progress = ((float) timeDiff) / ((float) mDuration); // 0..1
int level = ((int) (progress * posX.length)) % posX.length; // current value 0..posX.length

for (int i = 0; i < posX.length; i++) {
if ((i >= level && i < level + mAnimatedPoints) || level + mAnimatedPoints > posX.length && i < (level + mAnimatedPoints) % posX.length) {
float num = (i - level + posX.length) % posX.length; // 0..5
float size = mSize * (1 + (num * (1f / mAnimatedPoints)));
float sizeNext = mSize * (1 + ((num + 1) * (1f / mAnimatedPoints)));

float levelProgress = progress * posX.length - (int) (progress * posX.length);
float currentSize;
if (num == (mAnimatedPoints - 1)) {
// grow to next size
currentSize = mSize + (size - mSize) * levelProgress;
} else {
// shrink
currentSize = size + (sizeNext - size) * (1 - levelProgress);
}

canvas.drawCircle(posX[i], posY[i], currentSize, mPaint);
} else {
canvas.drawCircle(posX[i], posY[i], mSize, mPaint);
}
}

canvas.restoreToCount(save);
} else {
// draw normal
for (int i = 0; i < posX.length; i++) {
canvas.drawCircle(posX[i], posY[i], mSize, mPaint);
}
}
}

canvas.restoreToCount(save);
} else {
// draw normal
for (int i = 0; i < 16; i++) {
canvas.drawCircle(posX[i], posY[i], mSize, mPaint);
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
init();
}
}

@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
init();
}
@Override
public void setAlpha(int alpha) {

@Override
public void setAlpha(int alpha) {
}

}
@Override
public void setColorFilter(ColorFilter colorFilter) {

@Override
public void setColorFilter(ColorFilter colorFilter) {
}

}
@Override
public int getOpacity() {
return 0;
}

@Override
public int getOpacity() {
return 0;
}
@Override
public void start() {
if (mRunning) stop();
mRunning = true;
mStartTime = SystemClock.uptimeMillis();
invalidateSelf();
scheduleSelf(this, SystemClock.uptimeMillis() + FRAME_DELAY);
}

@Override
public void start() {
if (mRunning) stop();
mRunning = true;
mStartTime = SystemClock.uptimeMillis();
invalidateSelf();
scheduleSelf(this, SystemClock.uptimeMillis() + FRAME_DELAY);
}
@Override
public void stop() {
unscheduleSelf(this);
mRunning = false;
}

@Override
public void stop() {
unscheduleSelf(this);
mRunning = false;
}
@Override
public boolean isRunning() {
return mRunning;
}

@Override
public boolean isRunning() {
return mRunning;
}
@Override
public void run() {
invalidateSelf();
long uptimeMillis = SystemClock.uptimeMillis();
if (uptimeMillis + FRAME_DELAY < mStartTime + mDuration) {
scheduleSelf(this, uptimeMillis + FRAME_DELAY);
} else {
mRunning = false;
start();
}
}

@Override
public void run() {
invalidateSelf();
long uptimeMillis = SystemClock.uptimeMillis();
if (uptimeMillis + FRAME_DELAY < mStartTime + mDuration) {
scheduleSelf(this, uptimeMillis + FRAME_DELAY);
} else {
mRunning = false;
start();
public void setAnimatedPoints(int animatedPoints) {
mAnimatedPoints = animatedPoints;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public TestImageView(Context context, AttributeSet attrs, int defStyleAttr, int
}

private void init() {
setBackground(new RectProgressDrawable());
RectProgressDrawable drawable = new RectProgressDrawable();
setBackground(drawable);
}
}
21 changes: 12 additions & 9 deletions SpinningStar/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
Expand All @@ -11,14 +11,17 @@
android:background="@android:color/black"
tools:context="at.bleeding182.samples.spinningstar.MainActivity">


<!--<at.bleeding182.samples.spinningstar.TestImageView-->
<!--android:layout_width="200dp"-->
<!--android:layout_height="200dp"/>-->

<ProgressBar
android:id="@+id/progress"
android:layout_width="88dp"
android:layout_height="88dp"/>
android:layout_width="72dp"
android:layout_height="72dp"/>
<ProgressBar
android:id="@+id/progress2"
android:layout_width="72dp"
android:layout_height="72dp"/>
<ProgressBar
android:id="@+id/progress3"
android:layout_width="72dp"
android:layout_height="72dp"/>

</RelativeLayout>
</LinearLayout>
Binary file added SpinningStar/indeterminateProgressBars.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1cdec64

Please sign in to comment.