Android 自定义 Snackbar

1,072 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

Snackbar: Android 官方的一个控件,在 Android 应用中也算很常见了,用来显示应用交互中正在发生的消息,跟 Toast 类似,又有所区别,关于它的简单介绍和使用见上篇。Android 关于 Snackbar 基本使用

本篇,主要就是来实践一下自定义 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图片。

二、让自定义 Snackbar 布局类实现 ContentViewCallback 方法

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 也有两个实现,分别为 animateContentInanimateContentOut,它们是 Snackbar 的内容从屏幕上出现和消失时产生一些动画,我们可以在此设计它成为我们想要的动画。

三、继承 BaseTransientBottomBar

最终步骤了,其实我们点入 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(0000)
    }

    companion object {

        fun make(viewGroup: ViewGroup): CustomSnackbar {

            val customSnackbar = LayoutInflater.from(viewGroup.context).inflate(R.layout.custom_snackbar, viewGroup, falseas CustomSnackbarView

            return CustomSnackbar(viewGroup, customSnackbar)
        }
    }
}

调用运行:

CustomSnackbar.make(binding.root).show()

结果:

run

并且可以看到打印日志:

log

总结:

之所以我们需要自定义 Snackbar,还是源于需求,从 Snackbars Material Design 可以看到,它并不建议我们添加图片。

因此,我们如果还是需要在底部弹出带图片的 Snackbar,并且方便调用者调用,就可以考虑自定义 Snackbar 了。


🌈关注我吖~❤️

公众号:妮K妮K妮