Przejdź do treści
School IT / Przestrzeń do nauki

school-it.pl // android + kotlin // rozdział 6 // lekcja 20

Toast — komunikat wbudowany

Toast to krótki dymek na dole ekranu, który sam znika po kilku sekundach: „Zapisano”, „Skopiowano do schowka”, „Wysłano wiadomość”. Nie da się go kliknąć ani zamknąć — tylko informuje. W tej lekcji pokażesz Toast krótki i długi, z napisem z kodu i z zasobów, opanujesz „lawinę” Toastów i nauczysz się, kiedy Toast to zły wybór.

Kotlin Toast makeText LENGTH_SHORT / LONG cancel 1 × 45 min
CEL LEKCJI

Czego się dziś nauczysz

  • Pokażesz Toast z tekstem z kodu i z strings.xml.
  • Wybierzesz czas wyświetlania: krótki lub długi.
  • Zapamiętasz ostatni Toast i zastąpisz go nowym zamiast ustawiać w kolejce.
  • Zdecydujesz, kiedy zamiast Toasta użyć błędu przy polu, napisu albo okna dialogowego.
  • Poznasz ograniczenia Toastów w nowych wersjach Androida.
TEORIA

Jedna linia kodu

Toast nie potrzebuje żadnego wpisu w XML. Tworzysz go i pokazujesz w kodzie:

najprostszy Toast
Toast.makeText(this, "Zapisano notatkę", Toast.LENGTH_SHORT).show()
FragmentZnaczenie
Toast.makeText(…)Tworzy komunikat — jeszcze go nie pokazuje.
thisKontekst: aktywność, z której pochodzi komunikat.
"Zapisano notatkę"Tekst — napis albo identyfikator zasobu: R.string.zapisano.
Toast.LENGTH_SHORTCzas wyświetlania.
.show()Pokazuje komunikat. Bez tego nic się nie stanie.
12:30
Szybka notatka
Kupić zeszyt do matematyki i oddać książkę do biblioteki
Zapisz
Zapisano notatkę
Toast na dole ekranu (Android 12+ dodaje ikonę aplikacji)

this w listenerze

Wewnątrz setOnClickListener { … } słowo this nadal oznacza aktywność — Toast działa bez zmian. Wyjątkiem jest kod wewnątrz object : … (np. CountDownTimer z lekcji 15): tam this to ten obiekt, więc piszesz this@MainActivity.

TEORIA

Czas wyświetlania

StałaCzasKiedy
Toast.LENGTH_SHORTok. 2 sKrótkie potwierdzenie: „Zapisano”, „Skopiowano”.
Toast.LENGTH_LONGok. 3,5 sDłuższy tekst, który trzeba przeczytać.

Innych wartości nie ma — Toast.makeText(this, "…", 10000) nie da 10 sekund. Jeśli komunikat ma zostać na ekranie dłużej, to nie jest zadanie dla Toasta.

TEORIA

Lawina Toastów

Toasty ustawiają się w kolejce: gdy klikniesz przycisk dziesięć razy, zobaczysz dziesięć komunikatów, jeden po drugim, przez kilkanaście sekund. Rozwiązanie: zapamiętaj ostatni Toast w polu klasy i przed pokazaniem nowego anuluj stary:

zawsze najwyżej jeden Toast
private var ostatniToast: Toast? = null

private fun pokazToast(tekst: String) {
    ostatniToast?.cancel()                                     // usuń poprzedni, jeśli jest
    ostatniToast = Toast.makeText(this, tekst, Toast.LENGTH_SHORT)
    ostatniToast?.show()
}

Taka metoda pomocnicza ma jeszcze jedną zaletę: w całej klasie piszesz krótko pokazToast("Zapisano"), zamiast powtarzać długie Toast.makeText(…).show().

TEORIA

Kiedy Toast, a kiedy nie

Toast znika sam, nie da się go przeczytać ponownie i łatwo go przeoczyć. Dlatego nadaje się tylko do informacji, których przegapienie niczego nie psuje:

SytuacjaNajlepszy sposób
udana akcja: „Zapisano”, „Wysłano”Toast
błąd w konkretnym polu formularzaEditText.error przy polu (lekcja 06)
wynik, który użytkownik ma widziećTextView na ekranie
usunięcie, które można cofnąćSnackbar z przyciskiem „Cofnij” (lekcja 21)
pytanie: „Czy na pewno usunąć?”AlertDialog (lekcja 22)
TEORIA

Ograniczenia nowych Androidów

WersjaCo się zmieniło
Android 11 (API 30)setGravity nie działa dla zwykłego Toasta tekstowego — nie przesuniesz go na środek ekranu. Toast zawsze jest na dole.
Android 12 (API 31)Tekst Toasta ma najwyżej dwie linie, a obok pojawia się ikona aplikacji.

W starszych materiałach zobaczysz toast.setGravity(Gravity.CENTER, 0, 0). Kompiluje się, ale na nowych telefonach nic nie zmienia. Własny wygląd Toasta i jego ograniczenia poznasz w lekcji 21.

PRZYKŁAD

Szybka notatka

Pole na notatkę i trzy przyciski. Zapisz pokazuje krótki Toast „Zapisano notatkę”; pusta notatka nie daje Toasta, tylko błąd przy polu. Statystyki pokazuje długi Toast z liczbą znaków i słów. Kopiuj kopiuje tekst do schowka i potwierdza to Toastem z strings.xml. Wszystkie Toasty idą przez metodę pokazToast, więc szybkie klikanie nie tworzy kolejki.

12:30
Szybka notatka
Kupić zeszyt do matematyki i oddać książkę do biblioteki
Zapisz
Statystyki
Kopiuj do schowka
Znaków: 56, słów: 9
długi Toast ze statystykami
12:31
Szybka notatka
Wpisz notatkę…!
Notatka jest pusta
Zapisz
Statystyki
Kopiuj do schowka
pusta notatka — błąd przy polu, nie Toast

Przygotowanie projektu

  1. Nowy projekt Empty Views Activity, nazwa SzybkaNotatka, Kotlin, API 24.
  2. Dopisz tekst do strings.xml, podmień activity_main.xml i MainActivity.kt.
res/values/strings.xml — dopisz wewnątrz <resources>
<string name="skopiowano">Skopiowano do schowka</string>
res/layout/activity_main.xml — pełny plik
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_margin="16dp"
    android:fitsSystemWindows="true">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Szybka notatka"
        android:textSize="24sp"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/etNotatka"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:gravity="top"
        android:hint="Wpisz notatkę…"
        android:inputType="textMultiLine|textCapSentences"
        android:minLines="5" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnZapisz"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_marginEnd="8dp"
            android:text="Zapisz" />

        <Button
            android:id="@+id/btnStatystyki"
            style="@style/Widget.Material3.Button.OutlinedButton"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Statystyki" />
    </LinearLayout>

    <Button
        android:id="@+id/btnKopiuj"
        style="@style/Widget.Material3.Button.TextButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Kopiuj do schowka" />

</LinearLayout>
MainActivity.kt — pełny plik
package pl.schoolit.szybkanotatka

import android.content.ClipData
import android.content.ClipboardManager
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    // ---------- kontrolki ----------
    private lateinit var etNotatka: EditText
    private lateinit var btnZapisz: Button
    private lateinit var btnStatystyki: Button
    private lateinit var btnKopiuj: Button

    // ---------- stan ----------
    private var ostatniToast: Toast? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initUI()
        ustawZdarzenia()
    }

    private fun initUI() {
        etNotatka = findViewById(R.id.etNotatka)
        btnZapisz = findViewById(R.id.btnZapisz)
        btnStatystyki = findViewById(R.id.btnStatystyki)
        btnKopiuj = findViewById(R.id.btnKopiuj)
    }

    private fun ustawZdarzenia() {
        btnZapisz.setOnClickListener { zapisz() }
        btnStatystyki.setOnClickListener { pokazStatystyki() }
        btnKopiuj.setOnClickListener { kopiuj() }
    }

    // ---------- czynności ----------
    private fun zapisz() {
        val tekst = etNotatka.text.toString().trim()
        if (tekst.isEmpty()) {
            etNotatka.error = "Notatka jest pusta"     // błąd w polu — nie Toast
            return
        }
        pokazToast("Zapisano notatkę", Toast.LENGTH_SHORT)
    }

    private fun pokazStatystyki() {
        val tekst = etNotatka.text.toString().trim()
        val slowa = if (tekst.isEmpty()) 0 else tekst.split(Regex("\\s+")).size
        pokazToast("Znaków: ${tekst.length}, słów: $slowa", Toast.LENGTH_LONG)
    }

    private fun kopiuj() {
        val schowek = getSystemService(ClipboardManager::class.java)
        schowek.setPrimaryClip(ClipData.newPlainText("notatka", etNotatka.text))
        pokazToast(getString(R.string.skopiowano), Toast.LENGTH_SHORT)
    }

    // ---------- pomocnicze ----------
    // najwyżej jeden Toast naraz: nowy zastępuje stary
    private fun pokazToast(tekst: String, czas: Int) {
        ostatniToast?.cancel()
        ostatniToast = Toast.makeText(this, tekst, czas)
        ostatniToast?.show()
    }
}

Co dzieje się po kolei

  • Kod ma układ z lekcji 19: pola, krótki onCreate, initUI(), ustawZdarzenia() i metody czynności.
  • Pusta notatka to błąd danych, a nie informacja — dlatego zapisz() pokazuje error przy polu. Toast pojawia się tylko przy sukcesie.
  • split(Regex("\\s+")) dzieli tekst w miejscach, gdzie jest jedna lub więcej spacji albo nowych linii — podwójna spacja nie tworzy „pustego słowa”.
  • getSystemService(ClipboardManager::class.java) daje dostęp do schowka telefonu, a ClipData.newPlainText tworzy wpis z tekstem. Na Androidzie 13+ system sam pokazuje potwierdzenie kopiowania — nasz Toast jest dla starszych telefonów.
  • getString(R.string.skopiowano) odczytuje tekst z zasobów, więc tłumaczenie aplikacji obejmie też komunikat.
  • pokazToast anuluje poprzedni Toast, zanim pokaże nowy. Czas jest parametrem — metoda obsługuje oba rodzaje.

Sprawdź trzy rzeczy

  1. Kliknij Statystyki dziesięć razy szybko. Widać jeden Toast, który zmienia się od razu.
  2. W pokazToast zakomentuj linię ostatniToast?.cancel() i powtórz. Toasty ustawią się w kolejkę i będą się zmieniać jeszcze długo po ostatnim kliknięciu.
  3. Usuń .show() z pokazToast. Kod się skompiluje, ale żaden komunikat się nie pojawi.
ELEMENTY WBUDOWANE

Zestawienie elementów

ElementTypCo robi
Toast.makeText(kontekst, tekst, czas)ToastTworzy komunikat.
.show()metodaPokazuje komunikat.
.cancel()metodaUkrywa komunikat lub usuwa go z kolejki.
Toast.LENGTH_SHORT, Toast.LENGTH_LONGstałeOk. 2 s i ok. 3,5 s.
getString(R.string.…)StringTekst z zasobów.
this@MainActivitywyrażenieAktywność wewnątrz object : ….
getSystemService(ClipboardManager::class.java)usługaSchowek systemowy.
ClipData.newPlainText(etykieta, tekst)ClipDataWpis do schowka.
tekst.split(Regex("\\s+"))ListPodział na słowa po dowolnych odstępach.
CZĘSTE BŁĘDY

Zanim utkniesz

Zapis / objawProblem
Toast się nie pokazujeBrak .show() na końcu.
Toast.makeText(this, punkty, …) z liczbą IntAwaria Resources$NotFoundException: liczba jest traktowana jako identyfikator zasobu. Podaj napis: "Punkty: $punkty".
Toast w CountDownTimer — błąd kompilacji przy thisW object : … this to ten obiekt. Pisz this@MainActivity.
Toasty pojawiają się jeszcze długo po kliknięciachKolejka. Anuluj poprzedni przez cancel().
setGravity(Gravity.CENTER, 0, 0) nic nie zmieniaOd Androida 11 nie działa dla Toastów tekstowych.
Toast z błędem formularzaUżytkownik nie wie, którego pola dotyczy, a komunikat znika. Błąd pokazuj przy polu.
długi tekst uciętyOd Androida 12 najwyżej dwie linie. Skróć komunikat albo użyj okna dialogowego.
ZADANIA

Zadania

Każde zadanie wykonaj w nowym projekcie Empty Views Activity, w układzie z lekcji 19 (pola, initUI(), metody). Wskazówkę otwórz dopiero wtedy, gdy utkniesz.

ZAD 1Trzy przyciski, trzy Toasty★☆☆

Przyciski Krótki, Długi i Z zasobów. Pierwszy pokazuje Toast krótki, drugi długi, trzeci — tekst z strings.xml. Zmierz stoperem w telefonie, ile trwa każdy.

pokaż wskazówkę
  • Toast.makeText przyjmuje też identyfikator: Toast.makeText(this, R.string.powitanie, Toast.LENGTH_SHORT).
ZAD 2Rzut kostką z Toastem★☆☆

Przycisk Rzuć pokazuje wynik dużą cyfrą na ekranie, a przy wyrzuceniu szóstki dodatkowo Toast „Szóstka! Rzucasz jeszcze raz”. Szybkie klikanie nie może tworzyć kolejki Toastów.

pokaż wskazówkę
  • Wynik zawsze w TextView, a Toast tylko jako dodatek — skopiuj metodę pokazToast.
ZAD 3Toast w minutniku★★☆

Minutnik nauki: przycisk startuje 25-sekundowy CountDownTimer (udawane 25 minut). Co 5 sekund Toast „Zostało 20 minut” itd., a na koniec długi Toast „Czas na przerwę!”. Pasek postępu pokazuje upływ czasu.

pokaż wskazówkę
  • W onTick użyj this@MainActivity albo wywołaj metodę klasy pokazToast — wtedy problem z this znika sam.
ZAD 4Właściwy komunikat★★☆

Formularz rezerwacji stolika: imię, liczba osób (1–12), telefon. Przy kliknięciu Rezerwuj: błędy przy polach (nie Toasty), po sukcesie — Toast „Zarezerwowano stolik dla 4 osób” i podsumowanie w TextView, które zostaje na ekranie. Napisz w komentarzu na górze kodu, dlaczego podsumowanie nie może być tylko w Toaście.

pokaż wskazówkę
  • Kieruj się tabelą „Kiedy Toast, a kiedy nie”.
ZAD 5Licznik kliknięć z kamieniami milowymi★★☆

Duży przycisk-licznik. Toast pojawia się tylko przy kamieniach milowych: 10, 25, 50, 100 („Masz już 25 kliknięć!”). Przy 100 długi Toast „Mistrz klikania!” i przycisk się blokuje. Kamienie milowe trzymaj w tablicy.

pokaż wskazówkę
  • Sprawdzenie: if (klikniecia in kamienie), gdzie kamienie = intArrayOf(10, 25, 50, 100).
ZAD 6Toasty a dostępność★★★

Weź przykład z lekcji i włącz na emulatorze TalkBack. Sprawdź, czy Toasty są czytane na głos i ile razy przy szybkim klikaniu. Potem zmień aplikację tak, aby oprócz Toasta ostatni komunikat był zawsze widoczny w małym napisie pod przyciskami (ustawianym w pokazToast). Opisz w trzech zdaniach w komentarzu, komu taki stały napis pomaga.

pokaż wskazówkę
  • Pomyśl o osobach, które wolno czytają, mają słabszy wzrok albo odwróciły wzrok od ekranu w chwili pojawienia się Toasta.
PODSUMOWANIE

Co trzeba zapamiętać

  • Toast.makeText(this, tekst, Toast.LENGTH_SHORT).show() — bez show() nic się nie pojawi.
  • Są tylko dwa czasy: LENGTH_SHORT (ok. 2 s) i LENGTH_LONG (ok. 3,5 s).
  • Ostatni Toast trzymaj w polu i anuluj przed pokazaniem nowego.
  • Toast tylko do informacji, których przegapienie niczego nie psuje; błędy pokazuj przy polach, wyniki w TextView.
  • Od Androida 11 Toast tekstowy jest zawsze na dole, od Androida 12 ma najwyżej dwie linie.

Dokumentacja: Toast, Toasty — przewodnik.

Postęp zapisuje się w tej przeglądarce.