Android中按钮上的进度指示器

6

我正在Android项目中使用Material Design Button。当按钮被按下时,我想在按钮上创建一个进度指示器。看起来Material Design目前还没有支持它。

请问有没有人有建议,如何在Material Design Button中实现相同的效果。

谢谢。


https://proandroiddev.com/replace-progressdialog-with-a-progress-button-in-your-app-14ed1d50b44 - CTD
4个回答

5

我认为没有符合您需求的材料组件可用,但为其制作自定义布局非常容易,您可以使用约束布局并相应地放置视图。例如,您可以给进度条设置约束条件,使其位于按钮的中心位置。尝试以下操作,并检查它是否满足您的目的。

 <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

      <com.google.android.material.button.MaterialButton
            android:id="@+id/button_accept"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/dimen_24"
            android:layout_marginEnd="@dimen/dimen_24"
            android:backgroundTint="@color/colorGreen2"
            android:elevation="8dp"
            android:padding="@dimen/dimen_4"
            android:src="@drawable/ic_check_white"
            android:text="Accept"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ProgressBar
            android:id="@+id/progress_bar_accept"
            android:layout_width="@dimen/dimen_32"
            android:layout_height="@dimen/dimen_32"
            android:elevation="8dp"
            android:indeterminate="true"
            android:indeterminateTint="@color/colorWhite"
            android:indeterminateTintMode="src_in"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="@+id/button_accept"
            app:layout_constraintEnd_toEndOf="@+id/button_accept"
            app:layout_constraintStart_toStartOf="@+id/button_accept"
            app:layout_constraintTop_toTopOf="@+id/button_accept"/>

 </androidx.constraintlayout.widget.ConstraintLayout>

现在通过维护一些逻辑,如使用标志来保持其状态,处理进度条的可见性。

如果你需要了解约束布局,可以在这里查看: https://developer.android.com/reference/android/support/constraint/ConstraintLayout

希望这有所帮助。


2
但是在你的示例中,如果我将按钮的可见性更改为gone,那么进度条就不会出现在按钮上,因为就没有任何按钮了。进度条将没有按钮的边界/背景。 - Ankit
好的,所以您想隐藏按钮,然后显示进度条? - Parag Pawar
1
在这种情况下,您可以将一个按钮和进度条放置在另一个ConstraintLayout中,并为这个新创建的ConstraintLayout的进度条提供约束,而不是按钮。然后,即使隐藏按钮,您的进度条也会存在,因为它将具有ConstraintLayout的约束。 - Parag Pawar
1
我没有找到合适的解决方案。我正在改变进度条的可见性,并改变按钮文本的颜色,以便在我点击按钮时,进度条可以显示在按钮的顶部。 - Ankit

5

可以使用icon属性和androidx.swiperefreshlayout.widget.CircularProgressDrawable来实现这种行为。

xml

android:text='@{viewModel.isUpdating ? "" : @string/button_title}'
app:iconGravity="textStart"
app:iconPadding="0dp"
app:showProgress="@{viewModel.isUpdating}"

以及 BindingAdapter

@BindingAdapter("showProgress")
fun MaterialButton.setShowProgress(showProgress: Boolean?) {
    icon = if (showProgress == true) {
        CircularProgressDrawable(context!!).apply {
            setStyle(CircularProgressDrawable.DEFAULT)
            setColorSchemeColors(ContextCompat.getColor(context!!, R.color.colorTextPrimary))
            start()
        }
    } else null
    if (icon != null) { // callback to redraw button icon
        icon.callback = object : Drawable.Callback {
            override fun unscheduleDrawable(who: Drawable, what: Runnable) {
            }

            override fun invalidateDrawable(who: Drawable) {
                this@setShowProgress.invalidate()
            }

            override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) {
            }
        }
    }
}

1
如果能帮到某些人,这是Java版本+数据绑定。
private static Drawable getProgressBarDrawable(final Context context) {
        TypedValue value = new TypedValue();
        context.getTheme().resolveAttribute(android.R.attr.progressBarStyleSmall, value, false);
        int progressBarStyle = value.data;
        int[] attributes = new int[]{android.R.attr.indeterminateDrawable};
        TypedArray typedArray = context.obtainStyledAttributes(progressBarStyle, attributes);
        Drawable drawable = typedArray.getDrawable(0);
        typedArray.recycle();

        return drawable;
    }

@BindingAdapter(value = {"android:progressVisible"})
public static void setButtonLoading(MaterialButton button, boolean loading) {
        button.setMaxLines(1);
        button.setEllipsize(TextUtils.TruncateAt.END);
        button.setIconGravity(MaterialButton.ICON_GRAVITY_START);

        if (loading) {
            Drawable drawable = button.getIcon();
            if (!(drawable instanceof Animatable)) {
                drawable = getProgressBarDrawable(button.getContext());

                button.setIcon(drawable);
            }
            ((Animatable) drawable).start();
        } else {
            button.setIcon(null);
        }
    }

<com.google.android.material.button.MaterialButton
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:progressVisible="@{isLoading}"
    android:text="My loading button" />

0

感谢 @Aleksey 提供的想法。

我添加了一些代码,使用户体验更加完美。

XML:

 app:icon="@drawable/ic_in"
 android:text="@string/sign_in"
 app:iconGravity="textStart"
 app:iconSource="@{@drawable/ic_in}"
 app:showProgress="@{isLoading}"
 app:textSource="@{@string/sign_in}"

绑定适配器:

@BindingAdapter(value = ["showProgress", "iconSource", "textSource"], requireAll = false)
fun MaterialButton.setShowProgress(
    showProgress: Boolean?,
    iconSource: Drawable?,
    textSource: String?
) {
    icon = if (showProgress == true) {
        CircularProgressDrawable(context!!).apply {
            setStyle(CircularProgressDrawable.LARGE)
            setColorSchemeColors(ContextCompat.getColor(context!!, R.color.purple_200))
            start()
        }
    } else iconSource
    text = if (showProgress == true) "" else textSource
    if (icon != null) { // callback to redraw button icon
        icon.callback = object : Drawable.Callback {
            override fun unscheduleDrawable(who: Drawable, what: Runnable) {
            }

            override fun invalidateDrawable(who: Drawable) {
                this@setShowProgress.invalidate()
            }

            override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) {
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接