开发者

Android progressbar in button

Is there any possibility to show a spinning progress bar in a button? e.开发者_StackOverflow社区g. as background drawable?


I was having the same problem, so I created a specialized button for this: LoadingProgressButton

Include the button like this:

    <br.com.simplepass.loading_button_lib.CircularProgressButton
android:id="@+id/btn_id"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@drawable/circular_border_shape"
     app:spinning_bar_width="4dp" <!-- Optional -->
     app:spinning_bar_color="#FFF" <!-- Optional -->
     app:spinning_bar_padding="6dp" <!-- Optional -->

And use it like this:

    CircularProgressButton btn = (CircularProgressButton) findViewById(R.id.btn_id)
            btn.startAnimation(); 
                [do some async task. When it finishes]

                 //You can choose the color and the image after the loading is finished
                 btn.doneLoagingAnimation(fillColor, bitmap);
                 [or just revert de animation]
                 btn.revertAnimation();

Android progressbar in button


Yes.

You can create an AnimationDrawable, as described here, and then use the drawableLeft tag (for example) in your button's XML. like so:

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/your_background_drawable_resource"
        android:drawableLeft="@drawable/your_animation_drawable_resource"
        android:text="@string/your_text_res">
</Button>


Yes... Just wrap around both the button and progressBar inside a Relative Layout, like so...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/progressBar"
            android:layout_gravity="right"
            android:layout_alignTop="@+id/btnConnect"
            android:layout_alignRight="@+id/btnConnect"
            android:layout_alignEnd="@+id/btnConnect" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Connect"
            android:id="@+id/btnConnect"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="30dp"
            android:width="200dp"
            android:focusable="false"
            android:focusableInTouchMode="false" />
    </RelativeLayout>

    <TextView
        android:id="@+id/txtConnectStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btnConnect"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="Status : Not connected"
        android:textSize="12dp"
        android:layout_gravity="center_horizontal" />

    <LinearLayout
        android:orientation="vertical"

Wanted to post the sample image, but I don't have enough reputation just yet... ;)


I made a sample code like below.. I hope that my codes help you :)

[main.xml]

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

    <Button
        android:id="@+id/wheel_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/icon_spin_animation"
        />
</LinearLayout>

[icon_spin_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/wheel_db_update01" android:duration="50"/>
    <item android:drawable="@drawable/wheel_db_update02" android:duration="50"/>
    <item android:drawable="@drawable/wheel_db_update03" android:duration="50"/>
    <item android:drawable="@drawable/wheel_db_update04" android:duration="50"/>
    <item android:drawable="@drawable/wheel_db_update05" android:duration="50"/>
    <item android:drawable="@drawable/wheel_db_update06" android:duration="50"/>

 </animation-list>

[Activity Code]

public class ProgressOnTheButtonActivity extends Activity implements OnClickListener {
    /** Called when the activity is first created. */
     AnimationDrawable mFrameAnimation = null;

     boolean mbUpdating = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnWheel = (Button)findViewById(R.id.wheel_button);
        btnWheel.setOnClickListener(this);

        mFrameAnimation = (AnimationDrawable) btnWheel.getBackground();
    }

    public void onClick(View v) {
        if(v.getId() == R.id.wheel_button) {
            if(!mbUpdating) {
                mbUpdating = true;
                new AsyncTaskForUpdateDB().execute("");
            }
        }

    }

    private class AsyncTaskForUpdateDB extends AsyncTask<String, Integer, ResultOfAsyncTask> {      

        @Override
        protected void onPreExecute() {

            mFrameAnimation.start();
            super.onPreExecute();
        }

        @Override
        protected ResultOfAsyncTask doInBackground(String... strData) {
            ResultOfAsyncTask result = new ResultOfAsyncTask();

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return result;
        }

        @Override
        protected void onPostExecute(ResultOfAsyncTask result) {
            mFrameAnimation.stop();
            mbUpdating = false;
        }

        @Override
        protected void onCancelled() {
            mFrameAnimation.stop();
            mbUpdating = false;
            super.onCancelled();
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
        }
    }

    private class ResultOfAsyncTask {
        int iErrorCode = 0;
    }
}


To make Animatable drawables work, you need to extend the Button class and call Animatable.start() for drawables. I've made an implementation for this:

package com.example.yourapplication;

import android.content.Context;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatButton;
import android.util.AttributeSet;

public class AnimateCompoundDrawableButton extends AppCompatButton {

    public AnimateCompoundDrawableButton(Context context) {
        super(context);
    }

    public AnimateCompoundDrawableButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AnimateCompoundDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
        super.setCompoundDrawables(left, top, right, bottom);

        startIfAnimatable(left);
        startIfAnimatable(top);
        startIfAnimatable(right);
        startIfAnimatable(bottom);
    }

    @Override
    public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom) {
        super.setCompoundDrawablesRelative(start, top, end, bottom);

        startIfAnimatable(start);
        startIfAnimatable(top);
        startIfAnimatable(end);
        startIfAnimatable(bottom);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        // Makes a copy of the array, however we cannot do this otherwise.
        for (Drawable drawable : getCompoundDrawables()) {
            startIfAnimatable(drawable);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        // Makes a copy, however we cannot do this otherwise.
        for (Drawable drawable : getCompoundDrawables()) {
            stopIfAnimatable(drawable);
        }
    }

    private void startIfAnimatable(Drawable drawable) {
        if (drawable instanceof Animatable) {
            ((Animatable) drawable).start();
        }
    }

    private void stopIfAnimatable(Drawable drawable) {
        if (drawable instanceof Animatable) {
            ((Animatable) drawable).stop();
        }
    }
}


I have solved this problem by this way: first I have added progressBar and Button to common FrameLayout.

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="75dp"
        android:background="@color/white"
        android:layout_marginRight="20dp"
        android:layout_marginLeft="20dp">

        <Button
            android:id="@+id/buttonOnOff"
            android:layout_width="match_parent"
            android:layout_height="75dp"
            android:text="Включить"
            android:layout_gravity="center"
            android:visibility="visible"
            android:textColor="#FFFFFF"
            android:onClick="onClickIn"
            tools:ignore="OnClick" />

        <ProgressBar
            android:id="@+id/loading"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:indeterminateTintMode="src_atop"
            android:theme="@style/ActionBarProgress"
            />

</FrameLayout>

And after that I have turned on and turned off visibility of progressBar and changed text of Button where I need it.

final Button buttonOnOff = findViewById(R.id.buttonOnOff);
final ProgressBar pB = findViewById(R.id.pB);
buttonOnOff.setEnabled(false);
buttonOnOff.setText("");
pB.setVisibility(false);


Another Option is to use the nifty Spezi-Views, it contains a ProgressButton which is quite easy to use:

<de.halfreal.spezi.views.ProgressButton
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Press me"
        app:selectedText="I am loaded"
        app:unselectedText="Press me again"
        app:loadingDrawable="@drawable/spinner"
        />

and in code:

...
//show a rotation spinner, and no text (or the loading text)
progressButton.enableLoadingState();

//show no animation, but the selected/ unselected text
progressButton.disableLoadingState();
...


With Jetpack Compose you can use something like:

var progressIndicatorVisible by remember { mutableStateOf(false) }

 Button(onClick = {
     scope.launch {
         progressIndicatorVisible = true

         // Just for example
         delay(5000)
         progressIndicatorVisible = false
     }
 }, modifier = Modifier.animateContentSize()){
     if (progressIndicatorVisible) {
         CircularProgressIndicator(
             color = White,
             strokeWidth = 2.dp,
             modifier = Modifier.size(15.dp)
         )
     }
     Text ("Button",
         modifier = Modifier.padding(start = if (progressIndicatorVisible) 8.dp else 0.dp))
 }

Android progressbar in button

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜