Snackbar: Android 官方的一个控件,在 Android 应用中也算很常见了,用来显示应用交互中正在发生的消息,跟 Toast 类似,又有所区别,关于它的简单介绍和使用见上篇。Android 关于 Snackbar 基本使用。
本篇,主要就是来实践一下自定义 Snackbar。
view_custom_snackbar.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/secondaryRealgar_1A"
android:paddingHorizontal="@dimen/aroundMargins"
android:paddingVertical="@dimen/aroundMargins10">
<ImageView
android:id="@+id/img_logo"
android:layout_width="36dp"
android:layout_height="36dp"
android:src="@drawable/ic_status_accelerating"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/aroundMargins10"
android:text="You are Great!"
android:paddingHorizontal="@dimen/aroundMargins10"
android:paddingVertical="6dp"
android:background="@drawable/shape_cyan_stroke_20"
android:textColor="@color/baseCyan"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/img_logo"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这里示例布局就很简单的给一段文字右边添加了一张logo图片。
CustomSnackbarView.kt:
class CustomSnackbarView @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defaultStyle: Int = 0
) : ConstraintLayout(context, attributeSet, defaultStyle), ContentViewCallback {
private val binding = inflate<ViewCustomSnackbarBinding>()
init {
// ...
}
override fun animateContentIn(delay: Int, duration: Int) {
// TODO("Use some animation")
Log.i("yyyyy", "animateContentIn delay = $delay || duration = $duration")
}
override fun animateContentOut(delay: Int, duration: Int) {
// TODO("Use some animation")
Log.i("yyyyy", "animateContentOut delay = $delay || duration = $duration")
}
}
在这里可以在代码本身中自定义 Snackbar 的内容,更改文本消息,更新图像。默认情况就是我们在 xml 中定义的,可以看出来,我这里示例并没有做任何的修改,当然需要修改成啥还是根据需求来吧,可以灵活的给外部提供方法调用修改内容或者是图片。
这里 ContentViewCallback 也有两个实现,分别为 animateContentIn 和 animateContentOut,它们是 Snackbar 的内容从屏幕上出现和消失时产生一些动画,我们可以在此设计它成为我们想要的动画。
最终步骤了,其实我们点入 Snackbar 也可以看到,它继承了 BaseTransientBottomBar,因此可以猜到,我们需要自定义,当然也得走这一步。
Snackbar
然后我们也需要实现入口方法make(),现在先将 xml 视图创建好:
custom_snackbar.xml:
<?xml version="1.0" encoding="utf-8"?>
<com.viabtc.pool.main.mine.callboard.CustomSnackbarView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
然后是 CustomSnackbar.kt:
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.viabtc.pool.R
class CustomSnackbar(
parent: ViewGroup,
content: CustomSnackbarView
) : BaseTransientBottomBar<CustomSnackbar>(parent, content, content) {
init {
getView().setBackgroundColor(
ContextCompat.getColor(
view.context,
android.R.color.transparent
)
)
getView().setPadding(0, 0, 0, 0)
}
companion object {
fun make(viewGroup: ViewGroup): CustomSnackbar {
val customSnackbar = LayoutInflater.from(viewGroup.context).inflate(R.layout.custom_snackbar, viewGroup, false) as CustomSnackbarView
return CustomSnackbar(viewGroup, customSnackbar)
}
}
}
调用运行:
CustomSnackbar.make(binding.root).show()
结果:
run
并且可以看到打印日志:
log
之所以我们需要自定义 Snackbar,还是源于需求,从 Snackbars Material Design 可以看到,它并不建议我们添加图片。
因此,我们如果还是需要在底部弹出带图片的 Snackbar,并且方便调用者调用,就可以考虑自定义 Snackbar 了。