我正在Android项目中使用Material Design Button。当按钮被按下时,我想在按钮上创建一个进度指示器。看起来Material Design目前还没有支持它。
请问有没有人有建议,如何在Material Design Button中实现相同的效果。
谢谢。
我正在Android项目中使用Material Design Button。当按钮被按下时,我想在按钮上创建一个进度指示器。看起来Material Design目前还没有支持它。
请问有没有人有建议,如何在Material Design Button中实现相同的效果。
谢谢。
我认为没有符合您需求的材料组件可用,但为其制作自定义布局非常容易,您可以使用约束布局并相应地放置视图。例如,您可以给进度条设置约束条件,使其位于按钮的中心位置。尝试以下操作,并检查它是否满足您的目的。
<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
希望这有所帮助。
可以使用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) {
}
}
}
}
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" />
感谢 @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) {
}
}
}
}