6

I try to achieve a horizontal indeterminate ProgressBar, which will reverse its animation on end. To clarify, I want the progress bar to animate from 0 to 100, and afterwards back from 100 to 0. Here's a video of the standard animation, which I want to reverse on end.

According to documentation of ProgressBar this should be possible with xml, but i cannot achieve this. You can either set repeat (standard?) or cycle (this is what I want)

Here's my implementation:

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="8dip"
    android:indeterminate="true"
    android:indeterminateOnly="true"      //tried "false" too
    android:indeterminateBehavior="cycle" // type "reverse" is the one from linked video?
    android:max="100" />

Tried with max-value, and different style-parents

However, I found the value android:indeterminateDuration="[value]" and set one to 1second, the other to 10seconds. In the end, both progressloaders had the same length, which leaves me with the thought, that the styles might be overwritten somewhere?!

Does anyone know how to fix this?

Bounty Update: Question solved, for a working example where indeterminateBehaviour is working

longi
  • 11,104
  • 10
  • 55
  • 89
  • What values are inherited from `style="?android:attr/progressBarStyleHorizontal"`? – Tim Jan 23 '17 at 14:18
  • @TimCastelijns: Actually, i don't know. That's the standard android parent. I have no idea, how to take a look into that values :-/ – longi Jan 23 '17 at 14:32
  • did you look at this: http://stackoverflow.com/a/6450417/1185737 – KunalK Jan 31 '17 at 13:42
  • @KunalK Yes, found this, but it's another topic. I'm simple looking for a working example where `android:indeterminateDuration` or `android:indeterminateBehavior ` really working within xml according to documentation and for next time i'm facing these problems – longi Jan 31 '17 at 15:45

5 Answers5

2

I couldn't find how to change the animator in the ProgressBar, so I'm suggesting you to go with your own drawable.

Draw the progress as a rectangle

In a trivial example, let's make the progress look like a rectangle:

res/drawable/vector_drawable_progress_indeterminate_horizontal.xml (name inspired by core/res/res/drawable/vector_drawable_progress_indeterminate_horizontal.xml)

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="10dp"
    android:width="100dp"
    android:viewportHeight="10"
    android:viewportWidth="100" >
        <group
            android:name="rect1_grp"
            android:scaleX="1" >
            <path
                android:pathData="M 0,0 h 100 v 10 h -100 Z"
                android:fillColor="?attr/colorControlActivated" />
        </group>
</vector>

Animate the horizontal scale

Of course, this rectangle is not animated at all, so you want to wrap it in an object that changes it's horizontal scale (scaleX of rect1_grp).

res/drawable/custom_progress.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector android:drawable="@drawable/vector_drawable_progress_indeterminate_horizontal"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <target
        android:animation="@anim/progress_indeterminate_horizontal_rect1"
        android:name="rect1_grp"/>
</animated-vector>

The only thing that's left to do, is to have your own animation:

res/anim/progress_indeterminate_horizontal_rect1:

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="1500"
        android:propertyName="scaleX"
        android:valueFrom="0"
        android:valueTo="1"
        android:valueType="floatType"
        android:repeatMode="reverse"
        android:repeatCount="infinite"/>

</set>

The animation grows the scale linearly from 0f to 1f, and repeats infinitely, with a reverse mode (which avoids having a sequence of two animators: one for the scale increase, and one for the decrease).

Enjoy

Now, all you have to do is use this drawable in res/layout/activity.xml:

<ProgressBar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="8dip"
    android:indeterminate="true"
    android:indeterminateDrawable="@drawable/custom_progress" />

Left to do

  • I stripped the progress to the bare minimum. You might want to have a background drawable. You might also want to restore the secondary progress.
  • You may customize the interpolator in the animation.
rds
  • 26,253
  • 19
  • 107
  • 134
  • So basically, use custom animation instead of `android:indeterminateBehavior="cycle"` and `android:indeterminateDuration="10000"`? I was wondering if these values might be overwritten by device settings or style, so that this is the reasion why I cannot make them work? – longi Feb 06 '17 at 15:56
2
<layer-list>
<item android:id="@android:id/background">
    <shape>
        <corners android:radius="2dip" />
        <gradient android:startColor="#43ffffff" android:centerColor="#43ffffff" android:centerY="0.75" android:endColor="#43ffffff" android:angle="270" />
    </shape>
</item>
<item android:id="@android:id/progress">
    <clip>
        <shape>
            <corners android:radius="2dip" />
            <gradient android:startColor="#fff" android:endColor="#fff" android:angle="270" />
        </shape>
    </clip>
</item>

uses this drawable

Look at this picture

Baqar Gogia
  • 367
  • 4
  • 17
1

You could add an event where, depending on factors known would programmatically do:

progressBar.setIndeterminate(true);

or

progressBar.setIndeterminate(false);

considering what style it is completely depends on your analysis of the data presented.

If you know it is always going to be indeterminate and have a consistently expected style of behavior add these xml properties:

android:indeterminate="true"
android:indeterminateDrawable="@drawable/progress_indeterminate_horizontal"
android:indeterminateOnly="false"
KoalaKoalified
  • 687
  • 4
  • 15
0

Another approach you can maybe follow is to use a determinate style, and set values from 0 to 100 and from 100 to 0 back again.:

   setProgress(100);
   // sleep animation duration
   setProgress(0);
   // sleep animation duration
   // repeat

I think this solution is less elegant than having a custom inderminateDrawble, because it requires to have this fake progress updates.

Community
  • 1
  • 1
rds
  • 26,253
  • 19
  • 107
  • 134
0

add this to your layout,

       <ProgressBar
        android:id="@+id/pbProcessing"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/frame_getgas"
        android:indeterminateOnly="true"/>