Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

Commit

Permalink
Add gradients support (close #1)
Browse files Browse the repository at this point in the history
  • Loading branch information
antonKozyriatskyi committed Feb 3, 2019
1 parent 6d00669 commit bd582c6
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 3 deletions.
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ Simple but customizable view for displaying progress
##### With background filling enabled/disabled
<img src="art/background-filling-1.png" width="30%" /> <img src="art/background-filling-2.png" width="30%" /> <img src="art/background-filling-3.png" width="30%" />

##### With gradients [linear, sweep and radial] (details [here](#gradients))
<img src="art/gradient_linear.png" width="30%" /> <img src="art/gradient_sweep.png" width="30%" /> <img src="art/gradient_radial.png" width="30%" />


## How to use

Expand All @@ -58,7 +61,9 @@ Add view to your layout:
app:startAngle="270"
app:textColor="#fffc59"
app:textSize="14sp"
app:fillBackground="false" />
app:fillBackground="false"
app:gradientType="linear"
app:gradientEndColor="@color/colorAccent" />
```

Since all attributes have default values, you can specify none of them. Thus following code also works:
Expand Down Expand Up @@ -106,6 +111,8 @@ circularProgress.getMaxProgress() // returns 10000
| Progress cap | `app:progressCap` | setter: `setProgressStrokeCap(cap)`<br/>getter: `getProgressStrokeCap()` | `CAP_ROUND` |
| Progress animation | `app:enableProgressAnimation` | setter: `setAnimationEnabled(enableAnimation)`<br/>getter: `isAnimationEnabled()` | `true` |
| Whether to fill background with progress background color | `app:fillBackground` | setter: `setFillBackgroundEnabled(enable)`<br/>getter: `isFillBackgroundEnabled()` | `false` |
| Gradient type | `app:gradientType` | setter: `setGradient(type, color)`<br/>getter: `getGradientType()` | `no_gradient` |
| End color of a gradient | `app:gradientEndColor` | - | - |

---

Expand Down Expand Up @@ -208,6 +215,38 @@ circularProgress.setInterpolator(new LinearInterpolator());

---

#### Gradients
`CircularProgressIndicator` supports 3 types of gradient:
- Linear
- Radial (doesn't look really good)
- Sweep

They can be setup using attribute `app:gradientType"` that accepts 4 values:
- `linear`
- `radial`
- `sweep`
- `no_gradient`- default one, can also be used to remove gradient
You also must specify end color using `app:gradientEndColor="color|reference"` attribute.

Or you can set it in code:
```java
int endColor = Color.MAGENTA;

/* Must be one of:
* - LINEAR_GRADIENT
* - RADIAL_GRADIENT
* - SWEEP_GRADIENT
* - NO_GRADIENT
* */
int gradientType = CircularProgressIndicator.LINEAR_GRADIENT;

circularProgress.setGradient(gradientType, endColor);

circularProgress.getGradientType(); //returns LINEAR_GRADIENT
```

---

### Download using Gradle

Add this in your root `build.gradle` at the end of `repositories` in `allprojects` section:
Expand Down
Binary file added art/gradient_linear.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/gradient_radial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/gradient_sweep.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.Dimension;
Expand Down Expand Up @@ -43,6 +48,11 @@ public class CircularProgressIndicator extends View {
public static final int CAP_ROUND = 0;
public static final int CAP_BUTT = 1;

public static final int NO_GRADIENT = 0;
public static final int LINEAR_GRADIENT = 1;
public static final int RADIAL_GRADIENT = 2;
public static final int SWEEP_GRADIENT = 3;

private static final int DEFAULT_PROGRESS_START_ANGLE = 270;
private static final int ANGLE_START_PROGRESS_BACKGROUND = 0;
private static final int ANGLE_END_PROGRESS_BACKGROUND = 360;
Expand Down Expand Up @@ -170,6 +180,22 @@ private void init(@NonNull Context context, @Nullable AttributeSet attrs) {

reformatProgressText();

final int gradientType = a.getColor(R.styleable.CircularProgressIndicator_gradientType, 0);
if (gradientType != NO_GRADIENT) {
final int gradientColorEnd = a.getColor(R.styleable.CircularProgressIndicator_gradientEndColor, -1);

if (gradientColorEnd == -1) {
throw new IllegalArgumentException("did you forget to specify gradientColorEnd?");
}

post(new Runnable() {
@Override
public void run() {
setGradient(gradientType, gradientColorEnd);
}
});
}

a.recycle();
}

Expand Down Expand Up @@ -269,6 +295,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
calculateBounds(w, h);

Shader shader = progressPaint.getShader();
if (shader instanceof RadialGradient) {
RadialGradient gradient = (RadialGradient) shader;
}
}

private void calculateBounds(int w, int h) {
Expand Down Expand Up @@ -674,6 +705,54 @@ public Interpolator getInterpolator() {
return animationInterpolator;
}

public void setGradient(@GradientType int type, @ColorInt int endColor) {
Shader gradient = null;

float cx = getWidth() / 2f;
float cy = getHeight() / 2f;

int startColor = progressPaint.getColor();

switch (type) {
case LINEAR_GRADIENT:
gradient = new LinearGradient(0f, 0f, getWidth(), getHeight(), startColor, endColor, Shader.TileMode.CLAMP);
break;
case RADIAL_GRADIENT:
gradient = new RadialGradient(cx, cy, cx, startColor, endColor, Shader.TileMode.MIRROR);
break;
case SWEEP_GRADIENT:
gradient = new SweepGradient(cx, cy, new int[]{startColor, endColor}, null);
break;
}

if (gradient != null) {
Matrix matrix = new Matrix();
matrix.postRotate(startAngle, cx, cy);
gradient.setLocalMatrix(matrix);
}

progressPaint.setShader(gradient);

invalidate();
}

@GradientType
public int getGradientType() {
Shader shader = progressPaint.getShader();

int type = NO_GRADIENT;

if (shader instanceof LinearGradient) {
type = LINEAR_GRADIENT;
} else if (shader instanceof RadialGradient) {
type = RADIAL_GRADIENT;
} else if (shader instanceof SweepGradient) {
type = SWEEP_GRADIENT;
}

return type;
}

@Retention(RetentionPolicy.SOURCE)
@IntDef({DIRECTION_CLOCKWISE, DIRECTION_COUNTERCLOCKWISE})
public @interface Direction {
Expand All @@ -684,6 +763,11 @@ public Interpolator getInterpolator() {
public @interface Cap {
}

@Retention(RetentionPolicy.SOURCE)
@IntDef({NO_GRADIENT, LINEAR_GRADIENT, RADIAL_GRADIENT, SWEEP_GRADIENT})
public @interface GradientType {
}

public interface ProgressTextAdapter {

@NonNull
Expand Down
8 changes: 8 additions & 0 deletions circularprogressindicator/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@

<attr name="fillBackground" format="boolean" />

<attr name="gradientEndColor" format="color|reference"/>
<attr name="gradientType" format="enum">
<enum name="no_gradient" value="0"/>
<enum name="linear" value="1"/>
<enum name="radial" value="2"/>
<enum name="sweep" value="3"/>
</attr>

</declare-styleable>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.Switch;

import java.util.ArrayList;
import java.util.HashMap;

import antonkozyriatskyi.circularprogressindicator.CircularProgressIndicator;


Expand Down Expand Up @@ -106,6 +112,50 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
circularProgress.setAnimationEnabled(isChecked);
}
});

Spinner gradientType = findViewById(R.id.sp_gradient_type);

final ArrayList<HashMap<String, String>> gradients = new ArrayList<>();
HashMap<String, String> gradient = new HashMap<>();
gradient.put("type", "No gradient");
gradient.put("value", "0");
gradients.add(gradient);

gradient = new HashMap<>();
gradient.put("type", "Linear");
gradient.put("value", "1");
gradients.add(gradient);

gradient = new HashMap<>();
gradient.put("type", "Radial");
gradient.put("value", "2");
gradients.add(gradient);

gradient = new HashMap<>();
gradient.put("type", "Sweep");
gradient.put("value", "3");
gradients.add(gradient);


gradientType.setAdapter(
new SimpleAdapter(
this,
gradients,
android.R.layout.simple_dropdown_item_1line,
new String[]{"type"},
new int[]{android.R.id.text1}
));

gradientType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
circularProgress.setGradient(Integer.parseInt(gradients.get(position).get("value")), Color.MAGENTA);
}

@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}

@Override
Expand Down Expand Up @@ -154,12 +204,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

@Override
Expand Down
5 changes: 5 additions & 0 deletions example/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@
android:checked="true"
android:text="Enable animation" />

<Spinner
android:id="@+id/sp_gradient_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<Button
android:id="@+id/btn_progress_color"
android:layout_width="match_parent"
Expand Down

0 comments on commit bd582c6

Please sign in to comment.