Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying the resource image of Progress Bar

Tags:

I want to create a progress bar for Android. I have four images for my square shaped progress bar.

I am using the android defined progress bar:

<ProgressBar
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     style="@android:style/Widget.ProgressBar.Small"
     android:layout_marginRight="5dp" />

But if I want to make a square instead of the circle how can I do it? How do I pass my 4 images to the progress bar?

example:

enter image description here

like image 472
J_Strauton Avatar asked Dec 30 '15 19:12

J_Strauton


People also ask

How can I customize my Android progress bar?

Android App Development for Beginners This example demonstrates how to create a custom Progress Bar in Android using Kotlin. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.

What is progress bar in Android?

Android ProgressBar is a graphical view indicator that shows some progress. Android progress bar displays a bar representing the completing of the task. Progress bar in android is useful since it gives the user an idea of time to finish its task.

Which of the following can you use to display a progress bar in an Android application?

app. ProgressDialog class to show the progress bar. Android ProgressDialog is the subclass of AlertDialog class. The ProgressDialog class provides methods to work on progress bar like setProgress(), setMessage(), setProgressStyle(), setMax(), show() etc.


3 Answers

Generally you do have 2 options:

1. As already mentioned, use an animation-list and just swap pictures.

This one is probably the easier solution, since they can relatively easy be animated with AnimationDrawable. The only drawback would be that you need at least 16 images (in all resolutions) for your given result.

2. Use a custom drawable.

This is the more complicated approach. You will have to do the drawing and animating yourself, which is a hard task for most people with little good documentation.

Therefore you have to extends Drawable implements Runnable, Animatable and supply some good implementations.

The following is a basic impelmentation, calculating the positions once, then drawing them. The animation (the size of the individual circles) can and should be further tweaked ;)

Result in 3 variants:
Progree Bars

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();
        }
    }

    private void init() {
        if (mPaint == null) {
            mPaint = new Paint();
            mPaint.setColor(Color.WHITE);
            mPaint.setAntiAlias(true);
            mPaint.setStyle(Paint.Style.FILL);
        }

        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) {
        if (isRunning()) {
            // animation in progress
            final int save = canvas.save();

            long timeDiff = SystemClock.uptimeMillis() - mStartTime;

            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);
            }
        }
    }

    @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 setColorFilter(ColorFilter colorFilter) {

    }

    @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 stop() {
        unscheduleSelf(this);
        mRunning = false;
    }

    @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();
        }
    }

    public void setAnimatedPoints(int animatedPoints) {
        mAnimatedPoints = animatedPoints;
    }
}

Use with

    ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress);
    progressBar.setIndeterminateDrawable(new RectProgressDrawable());
    progressBar.setIndeterminate(true);

Alternatively you can see the full source code in a working project here

like image 79
David Medenjak Avatar answered Sep 25 '22 23:09

David Medenjak


I'm doing it with bunch of images and animation-list:

<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/loadingAnimationImageView"
    android:layout_width="36dp"
    android:layout_height="36dp"
    android:background="@drawable/loading_progress_indicator_animation" />

And res\drawable\loading_progres_indicator_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/selected"
    android:oneshot="false">
    <item
        android:drawable="@drawable/loading_progress_indicator_0"
        android:duration="40" />
    <item
        android:drawable="@drawable/loading_progress_indicator_1"
        android:duration="40" />
    <item
        android:drawable="@drawable/loading_progress_indicator_2"
        android:duration="40" />
    .....
    <item
        android:drawable="@drawable/loading_progress_indicator_11"
        android:duration="40" />
    <item
        android:drawable="@drawable/loading_progress_indicator_12"
        android:duration="40" />
</animation-list>

Where every loading_progress_indicator_XX image is a state of progress indicator.

The custom view with indicator:

public final class LoadingAnimationView extends FrameLayout {

    ImageView loadingAnimationImageView;
    AnimationDrawable loadingProgressAnimation;
    Handler handler = new Handler(Looper.getMainLooper());

    public LoadingAnimationView(Context context) {
        super(context);
        initialize();
    }

    private void initialize() {
        LayoutInflater.from(getContext()).inflate(R.layout.view_loading_videoview, this);
        loadingAnimationImageView = (ImageView)getView().findViewById(R.id.loadingAnimationImageView);
        loadingProgressAnimation = (AnimationDrawable) loadingAnimationImageView.getBackground();
        adaptToVisibility(getVisibility());
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        adaptToVisibility(visibility);
    }

    void adaptToVisibility(final int visibility) {
        if (visibility == VISIBLE) {
            loadingProgressAnimation.start();
            //This is to avoid "blinking" of progress indicator (if page is loading from cache)
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    loadingAnimationImageView.setVisibility(visibility);
                }
            }, 200);
        } else {
            loadingProgressAnimation.stop();
            loadingAnimationImageView.setVisibility(visibility);
        }
    }
}

As a result, in my case it looks like:

enter image description here

So all you will need is the states of your indicator & custom view like the one above.

To get states of your indicator, you can convert gif to list of pngs I'd suggest to use EzGif service:

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here

Another option - you can re-use one of dozens custom implementations of loading indicator like this one (it has some close enough to yours indicators) or this one (though, most of opensource indicators are circular).

I hope it helps.

like image 37
Konstantin Loginov Avatar answered Sep 27 '22 23:09

Konstantin Loginov


Yes, you need to create a custom view for this, but there is an additional Android library which could be helpful for you.

Please check: https://github.com/mrwonderman/android-square-progressbar

Examples of using this library:

enter image description here enter image description here enter image description here enter image description here enter image description here

Check also this: How to make a Square progress-bar with changing color in certain time interval?

Here you would find how to create your own implementation of this lib.

Hope it help

like image 4
piotrek1543 Avatar answered Sep 27 '22 23:09

piotrek1543