Creating Snackbars and Toasts Using XML

In Android development, providing feedback to users about an action they’ve taken or an event that has occurred is crucial for a good user experience. While both Snackbars and Toasts serve this purpose, they differ in their functionality and intrusiveness. Toasts are simple, non-intrusive messages that appear briefly and don’t require any user interaction. Snackbars, on the other hand, are more interactive, allowing users to dismiss them or perform an action.

While it’s common to create Snackbars and Toasts programmatically in Java or Kotlin, sometimes it’s useful to define them directly in XML. This approach simplifies your code and can be more readable, especially for simple messages. However, direct XML declaration of Snackbar or Toast is not supported, but this guide will provide methods with Material Components and Workarounds for handling these use cases in your Application via other approaches. Here are methods to implement their functional equivalents, focusing on using XML efficiently to define related visual properties.

Understanding Toasts and Snackbars

Toasts

Toasts are lightweight messages that appear on the screen for a brief period. They are primarily used for displaying system or application-level notifications to the user. They automatically disappear after a timeout period.

Key Features:

  • Non-intrusive: Doesn’t interrupt the user’s activity.
  • Automatic dismissal: Disappears after a short duration.
  • Simple message display: Primarily for informational messages.

Snackbars

Snackbars provide brief messages about app processes. They appear at the bottom of the screen on mobile and can contain an optional action. Snackbars automatically disappear after a timeout or after a user action.

Key Features:

  • Interactive: Allows users to perform an action or dismiss the message.
  • Part of the UI: Appears as an overlay on the app content.
  • Material Design component: Follows Material Design guidelines for visual appearance and behavior.

Why Not Directly Declare Snackbars/Toasts in XML?

Android’s framework doesn’t support the direct declaration of Snackbars or Toasts in XML layouts. These components are designed to be dynamically created and displayed from your application code, as their content often depends on runtime conditions and user actions.

Reasons:

  • Dynamic Content: Snackbar and Toast content usually needs to change based on app state, and these changes need to be controlled by the applications code.
  • Interaction Requirement: Snackbar, in particular requires dynamic creation in code, since they can respond to user actions

Workaround and Alternatives Approaches: Using Dialogs for Simple Snackbars

Since XML can’t directly create snackbars, simulate simple Snackbars for declarative definition of visual style.

Step 1: Define a Custom Layout

Create an XML layout for your custom Snackbar. This layout will contain the message and an optional action button.


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_snackbar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/design_default_color_primary"
    android:orientation="horizontal"
    android:padding="16dp">

    <TextView
        android:id="@+id/snackbar_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textColor="@android:color/white"
        android:textSize="16sp"/>

    <Button
        android:id="@+id/snackbar_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/design_default_color_secondary"/>
</LinearLayout>

Step 2: Inflate the Layout in Your Activity/Fragment

Inflate this layout in your Java/Kotlin code when you want to show the Snackbar-like message.


// Java Example
LayoutInflater inflater = getLayoutInflater();
View snackbarLayout = inflater.inflate(R.layout.custom_snackbar_layout, null);

TextView textView = snackbarLayout.findViewById(R.id.snackbar_text);
textView.setText("Your message here");

Button actionButton = snackbarLayout.findViewById(R.id.snackbar_action);
actionButton.setText("Action");
actionButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Handle action
    }
});

Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "", Snackbar.LENGTH_SHORT);
snackbar.getView().setPadding(0, 0, 0, 0);
Snackbar.SnackbarLayout snackbarLayoutView = (Snackbar.SnackbarLayout) snackbar.getView();
snackbarLayoutView.addView(snackbarLayout, 0);

snackbar.show();

// Kotlin Example
val snackbarLayout = layoutInflater.inflate(R.layout.custom_snackbar_layout, null)

snackbarLayout.findViewById(R.id.snackbar_text).text = "Your message here"

val actionButton = snackbarLayout.findViewById

Step 3: Use A Bottom Sheet As Alternative

Alternative way to define Snackbar layout is using a BottomSheetDialog


<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bottomSheetContainer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="Are you sure, you want to Delete this Post?"
        android:textColor="@color/black"
        android:textSize="16sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="24dp"
        android:gravity="end"
        android:orientation="horizontal"
        android:paddingEnd="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView">

        <com.google.android.material.button.MaterialButton
            android:id="@+id/cancelButton"
            style="?attr/borderlessButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:text="Cancel"
            android:textColor="@color/black"
            app:cornerRadius="8dp" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/deleteButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:backgroundTint="#F44336"
            android:text="Delete"
            android:textColor="@color/white"
            app:cornerRadius="8dp" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Instantiate the BottomSheet in code for interactivity.


        val dialog = BottomSheetDialog(this@MainActivity)
        val view = layoutInflater.inflate(R.layout.bottom_sheet_dialog,null)
        dialog.setContentView(view)

        val btnCancel = view.findViewById<Button>(R.id.cancelButton)
        val btnDelete = view.findViewById<Button>(R.id.deleteButton)

        btnCancel.setOnClickListener {
            dialog.dismiss()
        }

        btnDelete.setOnClickListener {
            Toast.makeText(this@MainActivity, "Deleted", Toast.LENGTH_SHORT).show()
            dialog.dismiss()
        }
        dialog.show()

Important : Using an existing layout to simulate Snackbar.

Considerations

  • Customization: For snackbars and toast messages, customizing messages is crucial to delivering a high quality UX for user action prompts
  • Alternatives for Snackbars and Notifications: Consider the bottom Sheet Dialogues. This is because of Bottom SheetDialog provides a native, style-based and action focused visual cue. This solution ensures full compatibility across Android versions

Conclusion

Although native Android Snackbar and Toast elements do not directly support inflation from XML layout resources, there are useful approaches with components like BottomSheetDialogs can enable similar declarative definitions, allowing you to create stylised action oriented components via static definition to achieve consistent styles to simulate native android functions . While direct declaration isn’t possible, structuring layout and behavior code improves separation of concerns in your applications