Aishvarya Jaiswal
Aishvarya Jaiswal

Reputation: 1811

How to make progress bar fill slowly

I have a progressbar in drawable. I want it to fill slowly whenset progress is done. That is it I should be able to see it filling, not in a flash. Also I have a texview inside that progressbar, I want that textview to keep revolving and as soon as the set progress filling completes, the textview should stop revolving and display progress.

Here is my code:

Layout:

    <ProgressBar
        android:id="@+id/circularProgressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="150dip"
        android:layout_height="150dip"
        android:layout_centerInParent="true"
        android:indeterminate="false"
        android:max="100"
        android:progress="0"
        android:progressDrawable="@drawable/progressbar" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="47sp"
        android:textStyle="bold"
        android:textColor="@color/Theme" />
</RelativeLayout>

progressbar.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:id="@android:id/background">
        <shape
            android:innerRadiusRatio="3"
            android:shape="ring"
            android:thicknessRatio="7.0"
            android:useLevel="false" >
            <solid android:color="@color/Red" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <shape
            android:innerRadiusRatio="3"
            android:shape="ring"
            android:thicknessRatio="7.0" >
            <solid android:color="@color/Theme" />
        </shape>
    </item>

</layer-list>

Also, I have a textview inside this progressbar, I want it to keep rotating until the progress is done. How to do that, I have an animation for that but it is not working. Here is the code:

rotate.xml

<rotate xmlns:android="http://schemas.android.com/apk/res/android" >
android:duration="4000"
android:fromdegrees="0"
android:pivotx="50%"
android:pivoty="50%"
android:todegrees="360"
android:toyscale="0.0"

</rotate>

It gives warnings like this: Unexpected text found in layout file: "android:fromdegrees="0" android:pivotx="50%" android:pivoty="50%" android:todegrees="360" android:to..."

Upvotes: 0

Views: 5190

Answers (5)

Android Developer
Android Developer

Reputation: 9643

Below is the code I am using for gradually filling circular progressbar-

xml

<ProgressBar
        android:id="@+id/progress"
        android:layout_width="100dp"
        android:layout_height="100dp"
        style="?android:attr/progressBarStyleHorizontal"
        android:indeterminate="false"
        android:layout_centerInParent="true"
        android:max="100"
        android:visibility="gone"
        android:progressDrawable="@drawable/background" />

background.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@android:id/secondaryProgress">
        <shape
            android:innerRadiusRatio="3"
            android:shape="ring"
            android:useLevel="true"
            android:thicknessRatio="14.0">

            <gradient
                android:startColor="#999999"
                android:endColor="#999999"
                android:centerColor="#999999"
                android:type="sweep" />
        </shape>
    </item>
    <item android:id="@android:id/background">
        <shape
            android:innerRadiusRatio="3"
            android:shape="ring"
            android:thicknessRatio="14.0"
            android:useLevel="false" >
            <solid android:color="@color/white" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <rotate
            android:fromDegrees="270"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="270" >
            <shape
                android:innerRadiusRatio="3"
                android:shape="ring"
                android:useLevel="true"
                android:thicknessRatio="14.0">
                <rotate
                    android:fromDegrees="0"
                    android:toDegrees="360"
                    android:pivotX="50%"
                    android:pivotY="50%" />
                <gradient
                    android:startColor="#8E58D4"
                    android:endColor="#8E58D4"
                    android:centerColor="#8E58D4"
                    android:type="sweep" />
            </shape>
        </rotate>
    </item>
</layer-list>

Code

 mProgressBar = (ProgressBar) activity.findViewById(R.id.progress);
 Resources res = getResources();
 Drawable drawable = res.getDrawable(R.drawable.background);
mProgressBar.setProgressDrawable(drawable);
ObjectAnimator animation = ObjectAnimator.ofInt(mProgressBar, "progress", 0, 100);
 animation.setDuration(10000);

Upvotes: 0

samsad
samsad

Reputation: 1241

Use this code it will help you.

Required Stuff:

  1. CustomProgressDialog
  2. anim
  3. drawble
  4. layout

1) CustomProgressDialog

package com.est.framework.android.ui;

import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.sc.restclient.R;

// TODO: Auto-generated Javadoc
/**
 * The Class CustomProgressDialog.
 */
public class CustomProgressDialog extends Dialog {

    /**
     * Instantiates a new custom progress dialog.
     *
     * @param context the context
     * @param theme the theme
     */
    public CustomProgressDialog(Context context, int theme) {
        super(context, theme);
    }

    /* (non-Javadoc)
     * @see android.app.Dialog#onWindowFocusChanged(boolean)
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        ImageView imageView = (ImageView) findViewById(R.id.loadingImageView);
        AnimationDrawable yourAnimation = (AnimationDrawable) imageView.getBackground();
        yourAnimation.start();
    }

    /**
     * Creates the dialog.
     *
     * @param context the context
     * @param title the title
     * @param message the message
     * @return the custom progress dialog
     */
    public static CustomProgressDialog createDialog(Context context,String title) {
        CustomProgressDialog dialog = new CustomProgressDialog(context,android.R.style.Theme_Panel);
        dialog.setContentView(R.layout.dialogimg);

        int width = ViewGroup.LayoutParams.MATCH_PARENT;
        int height = ViewGroup.LayoutParams.MATCH_PARENT;
        dialog.getWindow().setLayout(width, height);

        TextView mloadMsg = (TextView)dialog.findViewById(R.id.loadMsg);
        if (title != null) {
            mloadMsg.setText(title);
        }else{
            mloadMsg.setVisibility(View.GONE);
        }
        dialog.getWindow().getAttributes().gravity = Gravity.CENTER;
        dialog.setCancelable(false);
        return dialog;
    }
}

2) Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/pop_bg_bitmap"
    android:gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/loadingImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:background="@anim/loading_anim" />

    <TextView
        android:id="@+id/loadMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="10dp"
        android:layout_gravity="center_horizontal"
        android:textColor="@color/btn_stroke_text"
        android:text="Loading..." />

</LinearLayout>

3) Anim

<?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/progress_1" android:duration="500" />
    <item android:drawable="@drawable/progress_2" android:duration="500" />
    <item android:drawable="@drawable/progress_3" android:duration="500" />
    <item android:drawable="@drawable/progress_4" android:duration="500" />

</animation-list>

4) Drawable

  <?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android" 

    android:src="@drawable/fancybox_overlay"
    android:antialias="false"
    android:dither="true"
    android:tileMode="repeat"
    >
</bitmap>

Images :

  1. fancybox_overlay.png
  2. progress_1.png
  3. progress_2.png
  4. progress_3.png
  5. progress_4.png

Upvotes: 1

juung666
juung666

Reputation: 825

You may use Handler and Runnable.

Make the Handler execute postDelayed(yourRunnable, DELAY); in a new method called void next() or something.

In the run() method of yourRunnable, increase the progress position by X amount (very little, like 1 percent or something depending on your desire), and invalidate() your progress bar. After the progress bar increases the progress position by X amount, invoke next() again, which will, execute yourRunnable.run() again, which will increase the progress position by X amount (or you may gradually increase amount using a little more complex math, instead of static X amount), and so goes the cycle until the progress fills up to your desired amount.

private ProgressAnimator animator;

@Override
public void onDraw(Canvas c) {
  super.onDraw(c);
  if (animator.started) {
    animator.next();
  }
}

public void animateProgress(float end, IAnimator.PostAnimationAction postPostAnimationAction) {
  animator.start(end, postPostAnimationAction);
}

private class ProgressAnimator {

  static final long DELAY = 10;

  // NOTE:
  // "MULTIPLY_FACTOR" IS OPTIONAL. 
  // I USED THIS TO INCREASE THE PROGRESS SMOOTHLY AT 
  // DYNAMIC SPEED, NOT AT STATIC SPEED.
  // IF YOU WANT STATIC INCREASE OF THE PROGRESS,
  // DONT USE THIS.
  static final float MULTIPLY_FACTOR = 0.2f; 

  float endPosition;
  float remaining;
  boolean started;
  PostAnimationAction postAnimationAction;


  Handler handler = new Handler();
  Runnable runnable = new Runnable() {

    @Override
    public void run() {
      if (Math.abs(remaining) > 1) {
        raiseProgress(/* pass the current progress position here*/);
      } else {
        end();
      }
    }
  };

  /**
   * Constructor.
   *
   */
  ProgressSweepAnimator() {
    init();
  }

  @Override
  public void init() {
    started = false;
  }

  // NOTE:
  // "PostPostAnimationAction" IS OPTIONAL. I CREATED AND USED THIS 
  // BECAUSE I WANTED TO DO SOMETHING AFTER THE PROGRESS 
  // ANIMATION IS FINISHED.
  public void start(float endPosition, PostAnimationAction postPostAnimationAction) {
    this.endPosition = endPosition;
    start(postPostAnimationAction);
  }

  @Override
  public void start(PostAnimationAction postAnimationAction) {
    // Initialize status.
    started = true;
    this.postAnimationAction = postAnimationAction;

    // Find out the current progress.
    float start = /* get the current progress position here*/;

    remaining = end - start;
    raiseProgress(start);
  }

  @Override
  public void next() {
    handler.postDelayed(runnable, DELAY);
  }

  private void raiseProgress(float from) {
    float toRaise = remaining * MULTIPLY_FACTOR;
    remaining -= toRaise;

    raiseProgressTo(from + toRaise);
  }


  @Override
  public void end() {
    raiseTo(end);
    init();

    // NOTE:
    // THIS IS OPTIONAL BUT MAY BE VERY USEFUL, SO I 
    // JUST LEFT THIS OUT HERE.
    // Notify the subscriber about the completion of the Burst action.
    postAnimationAction.onActionComplete();
  }
}

Upvotes: 0

David Corsalini
David Corsalini

Reputation: 8208

Create a Property for the progress:

final Property<ProgressBar, Integer> progressProperty = new Property<ProgressBar, Integer>(
        int.class, "progress") {
    @Override
    public Integer get(ProgressBar object) {
        return object.getProgress();
    }

    @Override
    public void set(ProgressBar object, Integer value) {
        object.setProgress(value);
    }
};

Create and start an ObjectAnimator for that property on your ProgressBar (mProgressBar):

private void animateProgressBar(int targetProgress) {
    ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, progressProperty, targetProgress);
    anim.setInterpolator(new DecelerateInterpolator());
    anim.setDuration(300);
    anim.start();
}

You can costumize the animation with Interpolators, different duration, ecc

You can also use:

private void animateProgressBar(int targetProgress) {
    ObjectAnimator anim = ObjectAnimator.ofInt(mProgressBar, "progress", targetProgress);
    anim.setInterpolator(new DecelerateInterpolator());
    anim.setDuration(300);
    anim.start();
}

without declarying the Property, but I don't like this approach that much.

Upvotes: 1

Renji
Renji

Reputation: 26

I don't know about the text rotation, but for slowly increasing the progress bar, you can try this one:

mProgressBar is a global progress bar variable which is holding the instance of your progress bar

mProgress is a global integer variable initially set to 0, to monitor the current level of your progress bar.

pSize is the amount you want to increase the progress bar from the current level.

pSleepTime is the speed you want the progress bar to fill up. I usually use 50.

private void setProgressBar(int pSize, int pSleepTime) throws InterruptedException {

    for(int i=0;i<pSize && mProgress<100;i++){
        mProgress++;
        Thread.sleep(pSleepTime);
        mProgressBar.setProgress(mProgress);
    }
}

Upvotes: 0

Related Questions