Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách hiển thị Toast thông báo trên Android

Giới thiệu

Toast là thông báo nhẹ hiển thị ngắn gọn trên màn hình, tự động biến mất sau vài giây, không chặn tương tác người dùng. Dùng cho feedback đơn giản: "Đã lưu", "Lỗi kết nối", "Copied to clipboard"...

Cách dùng cơ bản

Toast.makeText() - Cú pháp chuẩn

// Java
Toast.makeText(context, "Nội dung thông báo", Toast.LENGTH_SHORT).show();

// Kotlin
Toast.makeText(context, "Nội dung thông báo", Toast.LENGTH_SHORT).show()
  • context: this (Activity), getApplicationContext(), view.context, requireContext() (Fragment).
  • LENGTH_SHORT (~2 giây), LENGTH_LONG (~3.5 giây).
  • Phải gọi .show() - quên gọi này là lỗi phổ biến.

Ví dụ hoàn chỉnh

Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnShortToast"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Toast SHORT (2s)" />

    <Button
        android:id="@+id/btnLongToast"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:text="Toast LONG (3.5s)" />

    <Button
        android:id="@+id/btnCustomToast"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:text="Custom Toast (Layout tùy chỉnh)" />
</LinearLayout>

Code (MainActivity.kt)

package com.example.toastdemo

import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.toastdemo.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnShortToast.setOnClickListener {
            Toast.makeText(this, "Đây là Toast SHORT", Toast.LENGTH_SHORT).show()
        }

        binding.btnLongToast.setOnClickListener {
            Toast.makeText(this, "Đây là Toast LONG - hiển thị lâu hơn", Toast.LENGTH_LONG).show()
        }

        binding.btnCustomToast.setOnClickListener {
            showCustomToast()
        }
    }

    private fun showCustomToast() {
        val inflater = layoutInflater
        val layout = inflater.inflate(R.layout.custom_toast, findViewById(R.id.custom_toast_container))

        val text = layout.findViewById(R.id.tvToastMessage)
        text.text = "Đây là Custom Toast với icon và màu sắc!"

        val toast = Toast(applicationContext)
        toast.duration = Toast.LENGTH_LONG
        toast.gravity = Gravity.CENTER
        toast.view = layout
        toast.show()
    }
}

Custom Toast Layout (res/layout/custom_toast.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/custom_toast_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="16dp"
    android:background="@drawable/toast_background"
    android:gravity="center_vertical">

    <ImageView
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_marginEnd="12dp"
        android:src="@android:drawable/ic_dialog_info"
        android:contentDescription="Icon" />

    <TextView
        android:id="@+id/tvToastMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="16sp" />
</LinearLayout>

Toast Background (res/drawable/toast_background.xml)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android">
    <solid android:color="#333333" />
    <corners android:radius="12dp" />
</shape>

Snackbar - Thay thế hiện đại cho Toast

Snackbar (Material Design) tốt hơn Toast:

  • Hiển thị ở bottom screen, có action button (Undo, Retry...).
  • Tương tác được (swipe to dismiss).
  • Animation mượt mà, Material Design 3.

Dependency: implementation("com.google.android.material:material:1.12.0")

// Snackbar cơ bản
Snackbar.make(binding.root, "Đã xóa mục", Snackbar.LENGTH_LONG).show()

// Snackbar với Action
Snackbar.make(binding.root, "Mục đã xóa", Snackbar.LENGTH_LONG)
    .setAction("Hoàn tác") { viewModel.undoDelete() }
    .setActionTextColor(Color.YELLOW)
    .show()

Lưu ý quan trọng

  • Toast chỉ hiển thị trên main thread. Nếu gọi từ background thread: runOnUiThread { Toast.makeText(...).show() }.
  • Không hiển thị nhiều Toast cùng lúc - chúng xếp hàng (queue).
  • Custom Toast: từ Android 12 (API 31), custom view toast bị hạn chế (chỉ text + icon). Khuyến nghị dùng Snackbar.
  • Trong Fragment: dùng requireContext() hoặc requireActivity() làm context.
  • Test trên Android 13+: Toast custom layout có thể không hiển thị đúng.

So sánh Toast vs Snackbar

Đặc điểmToastSnackbar
Vị tríBottom (fixed)Bottom (có animation)
Action buttonKhôngCó
Swipe dismissKhôngCó
Custom layoutHỗ trợ (bị hạn chế API 31+)Hỗ trợ đầy đủ
Material DesignKhôngCó (MD3)