Skip to content

Commit

Permalink
[Feature] Add determinate CircularProgressDrawable (#51)
Browse files Browse the repository at this point in the history
* Make sample labels more explicit

* Improve symmetry in progress style cases

the PROGRESS_STYLE_CIRCULAR block now works exactly as the
PROGRESS_STYLE_HORIZONTAL block

* Implement determinate circular progress bar

* Reduce BaseSingleCircularProgressDrawable's intristic size

on a 1x device, 16px was larger than the 14dp Small.NoPadding style size

* Add example page for Circular Determinate

* Move compositeAlpha to internal helper class Colors

* Add missing @OverRide annotation to getShowBackground()

* Implement secondary progress

* Document source if max level value

* Implement background color

* Pass progressDrawable into getTintTargetFromProgressDrawable

* Fix issue with setting secondary progress color

* f! implement background

* Implement mpb_determinateCircularStyle

* Add moving_start examples

* Link CircularDeterminateExamplesActivity

* Update naming: "Circular Determinate" -> Determinate Circular

* Reduce visibility of new classes

* Improve navigation in sample app

* Use Cap.BUTT instead of Cap.MITTER.

* [Refactor] Extract BaseProgressLayerDrawable; Rename classes; Minor refactoring.

* [Refactor] Refactor theme attribute value retrieval.

* [Fix] Fix secondary progress background emulation by drawing twice instead.

* [Refactor] Remove unused code.

* [Fix] Use framework indeterminateOnly instead of custom _forceIndeterminate.

* [Feature] Better default value for disabledAlpha.

* [Refactor] Minor refactoring.

* [Refator] Refactor MainActivity for circular determinate progress.

* [Refactor] Finish refactoring sample.

* [Refactor] Fix copyright headers.

* [Feature] Better layout spacing for determinate circular sample.

* [Feature] Make circular determinate progress start at 0; Minor refactoring.
  • Loading branch information
Simon Warta authored and Zhang Hai committed Apr 11, 2017
1 parent 1c8199f commit 2a841cf
Show file tree
Hide file tree
Showing 24 changed files with 861 additions and 195 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ In order to make your `ProgressBar` take the correct and consistent size on all
Available custom attributes:

- `app:mpb_progressStyle`: Style of progress drawable: `circular` or `horizontal`. Defaults to `circular`.
- `app:mpb_setBothDrawables`: Whether both determinate and indeterminate drawables should be set on this progress bar. Determinate circular progress drawable is not supported yet. Defaults to `false`.
- `app:mpb_setBothDrawables`: Whether both determinate and indeterminate drawables should be set on this progress bar. Defaults to `false`.
- `app:mpb_useIntrinsicPadding`: Whether progress drawable should use its intrinsic padding. Defaults to `true`.
- `app:mpb_showProgressBackground`: Whether progress drawable should show a progress background. Defaults to `true` for horizontal progress drawable, `false` otherwise.

Expand All @@ -80,7 +80,7 @@ Three Material Design drawables are backported to Android 4.0 (API 14), so you c

- [`HorizontalProgressDrawable`](library/src/main/java/me/zhanghai/android/materialprogressbar/HorizontalProgressDrawable.java)
- [`IndeterminateHorizontalProgressDrawable`](library/src/main/java/me/zhanghai/android/materialprogressbar/IndeterminateHorizontalProgressDrawable.java)
- [`IndeterminateProgressDrawable`](library/src/main/java/me/zhanghai/android/materialprogressbar/IndeterminateProgressDrawable.java)
- [`IndeterminateCircularProgressDrawable`](library/src/main/java/me/zhanghai/android/materialprogressbar/IndeterminateCircularProgressDrawable.java)

For example, to set a `IndeterminateHorizontalProgressDrawable` on a `ProgressBar`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Animatable;

import me.zhanghai.android.materialprogressbar.internal.ThemeUtils;
Expand All @@ -21,7 +22,7 @@ abstract class BaseIndeterminateProgressDrawable extends BaseProgressDrawable
@SuppressLint("NewApi")
public BaseIndeterminateProgressDrawable(Context context) {
int controlActivatedColor = ThemeUtils.getColorFromAttrRes(R.attr.colorControlActivated,
context);
Color.BLACK, context);
// setTint() has been overridden for compatibility; DrawableCompat won't work because
// wrapped Drawable won't be Animatable.
setTint(controlActivatedColor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import android.graphics.Color;
import android.graphics.Paint;

public abstract class BasePaintDrawable extends BaseDrawable {
abstract class BasePaintDrawable extends BaseDrawable {

private Paint mPaint;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2017 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com>
* All Rights Reserved.
*/

package me.zhanghai.android.materialprogressbar;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import me.zhanghai.android.materialprogressbar.internal.ThemeUtils;

class BaseProgressLayerDrawable<
ProgressDrawableType extends IntrinsicPaddingDrawable & ShowBackgroundDrawable
& TintableDrawable, BackgroundDrawableType extends IntrinsicPaddingDrawable
& ShowBackgroundDrawable & TintableDrawable>
extends LayerDrawable implements IntrinsicPaddingDrawable, MaterialProgressDrawable,
ShowBackgroundDrawable, TintableDrawable {

private float mBackgroundAlpha;

private BackgroundDrawableType mBackgroundDrawable;
private ProgressDrawableType mSecondaryProgressDrawable;
private ProgressDrawableType mProgressDrawable;

public BaseProgressLayerDrawable(Drawable[] layers, Context context) {
super(layers);

mBackgroundAlpha = ThemeUtils.getFloatFromAttrRes(android.R.attr.disabledAlpha, 0, context);

setId(0, android.R.id.background);
//noinspection unchecked
mBackgroundDrawable = (BackgroundDrawableType) getDrawable(0);
setId(1, android.R.id.secondaryProgress);
//noinspection unchecked
mSecondaryProgressDrawable = (ProgressDrawableType) getDrawable(1);
setId(2, android.R.id.progress);
//noinspection unchecked
mProgressDrawable = (ProgressDrawableType) getDrawable(2);

int controlActivatedColor = ThemeUtils.getColorFromAttrRes(R.attr.colorControlActivated,
Color.BLACK, context);
setTint(controlActivatedColor);
}

/**
* {@inheritDoc}
*/
@Override
public boolean getShowBackground() {
return mBackgroundDrawable.getShowBackground();
}

/**
* {@inheritDoc}
*/
@Override
public void setShowBackground(boolean show) {
if (mBackgroundDrawable.getShowBackground() != show) {
mBackgroundDrawable.setShowBackground(show);
mSecondaryProgressDrawable.setShowBackground(!show);
}
}

/**
* {@inheritDoc}
*/
@Override
public boolean getUseIntrinsicPadding() {
return mBackgroundDrawable.getUseIntrinsicPadding();
}

/**
* {@inheritDoc}
*/
@Override
public void setUseIntrinsicPadding(boolean useIntrinsicPadding) {
mBackgroundDrawable.setUseIntrinsicPadding(useIntrinsicPadding);
mSecondaryProgressDrawable.setUseIntrinsicPadding(useIntrinsicPadding);
mProgressDrawable.setUseIntrinsicPadding(useIntrinsicPadding);
}

/**
* {@inheritDoc}
*/
@Override
@SuppressLint("NewApi")
public void setTint(@ColorInt int tintColor) {
// Modulate alpha of tintColor against mBackgroundAlpha.
int backgroundTintColor = android.support.v4.graphics.ColorUtils.setAlphaComponent(
tintColor, Math.round(Color.alpha(tintColor) * mBackgroundAlpha));
mBackgroundDrawable.setTint(backgroundTintColor);
mSecondaryProgressDrawable.setTint(backgroundTintColor);
mProgressDrawable.setTint(tintColor);
}

/**
* {@inheritDoc}
*/
@Override
@SuppressLint("NewApi")
public void setTintList(@Nullable ColorStateList tint) {
ColorStateList backgroundTint;
if (tint != null) {
if (!tint.isOpaque()) {
Log.w(getClass().getSimpleName(),
"setTintList() called with a non-opaque ColorStateList, its original alpha will be discarded");
}
backgroundTint = tint.withAlpha(Math.round(0xFF * mBackgroundAlpha));
} else {
backgroundTint = null;
}
mBackgroundDrawable.setTintList(backgroundTint);
mSecondaryProgressDrawable.setTintList(backgroundTint);
mProgressDrawable.setTintList(tint);
}

/**
* {@inheritDoc}
*/
@Override
@SuppressLint("NewApi")
public void setTintMode(@NonNull PorterDuff.Mode tintMode) {
mBackgroundDrawable.setTintMode(tintMode);
mSecondaryProgressDrawable.setTintMode(tintMode);
mProgressDrawable.setTintMode(tintMode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2017 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com>
* All Rights Reserved.
*/

package me.zhanghai.android.materialprogressbar;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;

abstract class BaseSingleCircularProgressDrawable extends BaseProgressDrawable {

private static final RectF RECT_BOUND = new RectF(-21, -21, 21, 21);
private static final RectF RECT_PADDED_BOUND = new RectF(-24, -24, 24, 24);
private static final RectF RECT_PROGRESS = new RectF(-19, -19, 19, 19);

@Override
protected void onPreparePaint(Paint paint) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
}

@Override
protected void onDraw(Canvas canvas, int width, int height, Paint paint) {

if (mUseIntrinsicPadding) {
canvas.scale(width / RECT_PADDED_BOUND.width(), height / RECT_PADDED_BOUND.height());
canvas.translate(RECT_PADDED_BOUND.width() / 2, RECT_PADDED_BOUND.height() / 2);
} else {
canvas.scale(width / RECT_BOUND.width(), height / RECT_BOUND.height());
canvas.translate(RECT_BOUND.width() / 2, RECT_BOUND.height() / 2);
}

onDrawRing(canvas, paint);
}

protected abstract void onDrawRing(Canvas canvas, Paint paint);

protected void drawRing(Canvas canvas, Paint paint, float startAngle, float sweepAngle) {
// startAngle starts at 3 o'clock on a watch.
canvas.drawArc(RECT_PROGRESS, -90 + startAngle, sweepAngle, false, paint);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2017 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com>
* All Rights Reserved.
*/

package me.zhanghai.android.materialprogressbar;

import android.graphics.Canvas;
import android.graphics.Paint;

class CircularProgressBackgroundDrawable extends BaseSingleCircularProgressDrawable
implements ShowBackgroundDrawable {

private boolean mShow = true;

@Override
public boolean getShowBackground() {
return mShow;
}

@Override
public void setShowBackground(boolean show) {
if (mShow != show) {
mShow = show;
invalidateSelf();
}
}

@Override
public void draw(Canvas canvas) {
if (mShow) {
super.draw(canvas);
}
}

@Override
protected void onDrawRing(Canvas canvas, Paint paint) {
drawRing(canvas, paint, 0, 360);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2017 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com>
* All Rights Reserved.
*/

package me.zhanghai.android.materialprogressbar;

import android.content.Context;
import android.graphics.drawable.Drawable;

/**
* A new {@code Drawable} for determinate circular {@code ProgressBar}.
*
* Package private as this does only work together with MaterialProgressBar and is not suitable
* for another ProgressBar
*/
class CircularProgressDrawable extends BaseProgressLayerDrawable<SingleCircularProgressDrawable,
CircularProgressBackgroundDrawable> {

/**
* Create a new {@code CircularProgressDrawable}.
*
* @param context the {@code Context} for retrieving style information.
*/
CircularProgressDrawable(int style, Context context) {
super(new Drawable[] {
new CircularProgressBackgroundDrawable(),
new SingleCircularProgressDrawable(style),
new SingleCircularProgressDrawable(style),
}, context);
}
}
Loading

0 comments on commit 2a841cf

Please sign in to comment.