Custom Android Progress Views

in #utopian-io8 years ago (edited)

Repository

https://github.com/bxute/Custom-ProgressViews

Custom Android Progress Views


  • Bubbling Progress View
    bubbling.gif

  • Earthworm Progress View
    earthworm.gif

  • Ripple Progress View
    ripple.gif

Motivation of building it

Android SDK is equipped with default progress bar
Screen Shot 2018-06-04 at 12.07.32 AM.png

Sometimes we need a custom User experience with a new design and appearance behavior. There we require to write custom view from scratch.

In this project, I have tried to mock Windows Phone animation on Android platform.

Now comes the mechanics behind these.


Bubbling Progress View

Trigonometry helped a lot in achieving this.

Screen Shot 2018-06-04 at 12.38.14 AM.png

To achieve the animation

  • ValueAnimator is run from 0 to 360.
  • Updates are listened
  • Radiuses are calculated
  • Views are rendered

ValueAnimator class provides a simple timing engine for running animations which calculate animated values and set them on target objects.

We can listen to updates for intermediate angle values being animated by this class.
This returns a single value ranging from 0 to 360.

We consider this as Reference angle as you can see in the above illustration.
Each bubble is drawn in reference to the last bubble with a Phase Difference.

The phase difference is calculated by:

mPhaseDifference = 90 / (BUBBLE_COUNT - 1);

In order to draw a circle, we need its radius. In this Progress view, Max Radius of the bubble is fixed so that it can grow to that extent and then shrink down.

Now we need to calculate a radius of each circle. The radius of the circle depends on its phase difference, circle index(position of a circle from left to right) , max radius.

int radius = maxRadius * factor;

Here factor is nothing but y-intercept of the coordinate system for a given angle. Since its value range from 0 to 1, For 1 first circle we get 0 radii and for the last circle, we get the max radius.

Code for getting Factor:

private double getFactor(int animatedAngle, int circleIndex) {
        return Math.abs(Math.cos(getRadian((int)(animatedAngle + (circleIndex * mPhaseDifference)))));
}

This helper method will be used for calculating radii when we get an update from ValueAnimator.

Code snippet for ValueAnimator Update:

final ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 360);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                for (int i = 0; i < BUBBLE_COUNT; i++) {
                    radiuses[i] = mBubbleMaxRadiusInPx * getFactor((Integer) valueAnimator.getAnimatedValue(), i);
                }
                invalidate();
            }
        });

We are storing radiuses in a array and use this array while drawing each circle at the same time.

Code snippet for drawing :

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float originX = mBubbleMaxRadiusInPx;
        float originY = mBubbleMaxRadiusInPx;

        for (int i = 0; i < BUBBLE_COUNT; i++) {
            //draw circle
            canvas.drawCircle(originX, originY, (float) radiuses[i], mPaint);
            //prepare next origin info
            originX += 2 * mBubbleMaxRadiusInPx + mBubbleGapInPx;
        }
    }

Earthworm Progress View

The name seems funny 😀. I named it earthworm because its movement behavior resembles the movement of an earthworm.

Anyway, the mechanics behind this is Bezier curve.
This animation contains 3 phase of each dots.
Deaccelerate from left -> move with constant speed-> accelerate and go off the screen to right

If we imagine the movements, then we get something like

Screen Shot 2018-06-04 at 1.10.14 AM.png

This is a bezier curve of 3rd degree. To get this curve, we need 4 values ( startX , endX , startY , endY).
I found a very useful tool online to get these values: http://cubic-bezier.com/

Now i added Interpolator for ValueAnimator CubicBezierInterpolator.

Some lines of this interpolator:

public class CubicBezierInterpolator implements Interpolator {

    public static final CubicBezierInterpolator STANDARD_CURVE = new CubicBezierInterpolator(.33, .7, .7, 0.33);
    public static final CubicBezierInterpolator CURVE_TYPE_ONE = new CubicBezierInterpolator(.15,.79,.79,.15);

    protected PointF start;
    protected PointF end;
    protected PointF a = new PointF();
    protected PointF b = new PointF();
    protected PointF c = new PointF();


    public CubicBezierInterpolator(PointF start, PointF end) throws IllegalArgumentException {
        if (start.x < 0 || start.x > 1) {
            throw new IllegalArgumentException("startX value must be in the range [0, 1]");
        }
        if (end.x < 0 || end.x > 1) {
            throw new IllegalArgumentException("endX value must be in the range [0, 1]");
        }
        this.start = start;
        this.end = end;
    }

...
...

You can mention public static final CubicBezierInterpolator STANDARD_CURVE = new CubicBezierInterpolator(.33, .7, .7, 0.33);

The values provided in the constructor of this Class are the values responsible for such a movement.

But this is for 1 dot.
For other dots following the 1st dot, we just run the same animation but with some startDelay and finally we get this result.

You can use these in your projects just by copying the class into yours.
I will soon be releasing a Gradle dependency for this Android View.

This public repository is open for contributions and i would love to hear any suggestions.
Hope you liked it 😀.

Interpolator Code: is referred from https://gist.github.com/rocboronat/0ef85535c5cd352f10fe

GitHub Account

https://github.com/bxute

Commit : https://github.com/bxute/Custom-ProgressViews/commit/e574a7860740e1e08c3c97083efebffabac69c5b

Sort:  

Thank you for your contribution. Though in the current state, there is nothing unique in this project. Also taking code from other sources is not entertained in the Utopian. Your code in CubicBezierInterpolator is taken from https://gist.github.com/rocboronat/0ef85535c5cd352f10fe.

Please try to create something unique on your own.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Coin Marketplace

STEEM 0.04
TRX 0.32
JST 0.083
BTC 63631.22
ETH 1726.21
USDT 1.00
SBD 0.42