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

school-it.pl // android + kotlin // rozdział 2 // lekcja 04

TextView — wyświetlanie tekstu

TextView to najczęściej używana kontrolka Androida — każdy napis, tytuł, wynik czy komunikat na ekranie to TextView. Znasz go już z poprzednich lekcji. Teraz poznasz go dokładnie: jak ustawić wygląd tekstu w XML, jak go zmieniać z kodu Kotlin i jak poradzić sobie z tekstem, który się nie mieści.

Kotlin XML TextView text textSize setTextColor ellipsize 1 × 45 min
CEL LEKCJI

Czego się dziś nauczysz

  • Ustawisz rozmiar, kolor, styl i krój tekstu w XML.
  • Ograniczysz liczbę linii i dodasz wielokropek do zbyt długiego tekstu.
  • Zmienisz tekst z kodu, także łącząc go z wartościami zmiennych.
  • Zmienisz rozmiar i kolor tekstu z kodu.
  • Wylosujesz element z tablicy i pokażesz go na ekranie.
TEORIA

Wygląd tekstu w XML

Wygląd napisu ustawiasz atrybutami w pliku układu. Najważniejsze:

AtrybutPrzykładowa wartośćEfekt
android:text"@string/tytul"Treść napisu.
android:textSize"20sp"Rozmiar tekstu — zawsze w sp.
android:textColor"#C62828" lub "@color/akcent"Kolor tekstu.
android:textStyle"bold", "italic", "bold|italic"Pogrubienie, kursywa.
android:fontFamily"serif", "monospace", "sans-serif-light"Krój pisma.
android:textAllCaps"true"Wszystko wielkimi literami (tylko wyświetlanie).
android:gravity"center"Wyrównanie tekstu w napisie (lekcja 02).
android:lineSpacingExtra"6dp"Dodatkowy odstęp między liniami.
android:letterSpacing"0.1"Odstęp między literami (ułamek wysokości litery).
android:background"#FFF3E0"Tło napisu.
12:30
zwykły tekst 14sp
textSize=”22sp”
textStyle=”bold”
textStyle=”italic”
textColor=”#C62828″
fontFamily=”serif”
fontFamily=”monospace”
textAllCaps=”true”
letterSpacing=”0.15″
background=”#FFF3E0″
ten sam TextView z różnymi atrybutami

Kolor w zapisie #RRGGBB

Po znaku # są trzy pary cyfr szesnastkowych: ilość czerwonego, zielonego i niebieskiego, od 00 do FF. #000000 to czarny, #FFFFFF biały, #FF0000 czerwony. Można dodać przezroczystość na początku: #80000000 to półprzezroczysta czerń. Kolor wybierzesz też myszką — kliknij mały kwadracik koloru na marginesie edytora XML.

TEORIA

Długi tekst

Gdy tekst jest dłuższy niż szerokość napisu, TextView sam zawija go do kolejnych linii. Czasem tego nie chcesz — na przykład w liście wiadomości, gdzie każdy wiersz ma mieć tę samą wysokość. Wtedy ograniczasz liczbę linii i każesz uciąć tekst wielokropkiem:

napis ucięty po dwóch liniach
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxLines="2"
    android:ellipsize="end"
    android:text="@string/dlugi_opis" />
12:30
bez ograniczeń
Wycieczka klasowa do Gdańska: zbiórka o 7:30 przed szkołą, powrót około 19:00. Zabierz legitymację i drugie śniadanie.
maxLines=”2″ + ellipsize=”end”
Wycieczka klasowa do Gdańska: zbiórka o 7:30 przed szkołą, powrót około 19:00. Zabierz legitymację i drugie śniadanie.
ten sam tekst w dwóch napisach

wielokropek pokazuje użytkownikowi, że tekst jest dłuższy — sama treść w text się nie zmienia

ellipsize może mieć wartość end (wielokropek na końcu), start lub middle. Bez maxLines albo android:singleLine nie zadziała — tekst nie ma wtedy powodu, żeby się kończyć.

TEORIA

TextView w kodzie

Najpierw znajdujesz napis przez findViewById (lekcja 01), potem zmieniasz jego właściwości. Wszystko piszemy w onCreate, po setContentView:

MainActivity.kt — fragment onCreate
val tvWynik = findViewById<TextView>(R.id.tvWynik)

val punkty = 42
tvWynik.text = "Masz $punkty punktów"         // szablon napisu: $zmienna
tvWynik.append("\nGratulacje!")                // dopisuje na końcu
tvWynik.textSize = 24f                         // rozmiar w sp, liczba z literą f
val ile = tvWynik.text.length                  // odczyt: długość tekstu
ZapisZnaczenie
tv.text = "…"Zastępuje cały tekst.
"Masz $punkty pkt"Szablon napisu: w miejsce $punkty wstawi się wartość zmiennej.
"Razem: ${a + b}"W klamrach może być całe wyrażenie — zostanie obliczone.
tv.append("…")Dopisuje tekst na końcu, nie kasując poprzedniego.
tv.text.toString()Odczyt tekstu jako zwykłego napisu String.
tv.textSize = 24fUstawia rozmiar w sp. Litera f oznacza liczbę typu Float.

textSize: zapis w sp, odczyt w pikselach

tvWynik.textSize = 24f ustawia 24 sp. Ale odczyt tvWynik.textSize zwraca rozmiar w prawdziwych pikselach ekranu — na typowym telefonie około trzy razy więcej. Zapis tvWynik.textSize = tvWynik.textSize + 2 nie powiększy więc tekstu o 2 sp, tylko kilkukrotnie. Rozmiar trzymaj we własnej zmiennej.

TEORIA

Kolory z kodu

Metoda setTextColor przyjmuje kolor jako liczbę. Taką liczbę dostaniesz na trzy sposoby:

trzy sposoby podania koloru
tvWynik.setTextColor(Color.RED)                       // gotowa stała
tvWynik.setTextColor(Color.parseColor("#2E7D32"))     // zapis #RRGGBB
tvWynik.setTextColor(getColor(R.color.akcent))        // kolor z colors.xml
tvWynik.setBackgroundColor(Color.parseColor("#FFF3E0")) // tło napisu

Color to klasa z pakietu android.graphics — wymaga linii import android.graphics.Color. Najlepszy jest trzeci sposób: kolor ma nazwę i jest w jednym miejscu, tak jak w XML (lekcja 02).

Nie podawaj numeru zasobu jako koloru

tvWynik.setTextColor(R.color.akcent) skompiluje się, ale tekst będzie miał dziwny, prawie przezroczysty kolor. R.color.akcent to numer zasobu, a nie kolor — zamienia go na kolor dopiero getColor(…).

PRZYKŁAD

Przysłowie dnia

Przy każdym uruchomieniu aplikacja losuje jedno przysłowie z tablicy i pokazuje je dużą, pochyłą czcionką, a pod spodem jego znaczenie. Krótkie przysłowia mają większą czcionkę niż długie. Na dole jest napis z numerem przysłowia, a jego kolor zależy od tego, czy numer jest parzysty.

7:45
PRZYSŁOWIE DNIA
„Kto pyta, nie błądzi.”
Lepiej zapytać, niż zgadywać i popełnić błąd.
Przysłowie 4 z 6 · uruchom ponownie, aby wylosować inne
krótkie przysłowie — duża czcionka
→ponowne
uruchomienie
7:46
PRZYSŁOWIE DNIA
„Gdzie kucharek sześć, tam nie ma co jeść.”
Gdy za dużo osób zarządza jedną sprawą, nic się nie udaje.
Przysłowie 5 z 6 · uruchom ponownie, aby wylosować inne
długie przysłowie — mniejsza czcionka

numer parzysty — zielona stopka, nieparzysty — czerwona

Przygotowanie projektu

  1. Nowy projekt Empty Views Activity, nazwa PrzyslowieDnia, Kotlin, API 24.
  2. Do colors.xml dopisz kolor fiolet. Podmień strings.xml, activity_main.xml i MainActivity.kt.
res/values/colors.xml — dopisz wewnątrz <resources>
<color name="fiolet">#6750A4</color>
res/values/strings.xml — pełny plik
<resources>
    <string name="app_name">Przysłowie dnia</string>
    <string name="naglowek">Przysłowie dnia</string>
</resources>
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:letterSpacing="0.15"
        android:text="@string/naglowek"
        android:textAllCaps="true"
        android:textColor="@color/fiolet"
        android:textSize="14sp"
        android:textStyle="bold" />

    <!-- tekst wpisze kod; krój i styl ustawione tutaj -->
    <TextView
        android:id="@+id/tvPrzyslowie"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:fontFamily="serif"
        android:textSize="30sp"
        android:textStyle="italic" />

    <TextView
        android:id="@+id/tvZnaczenie"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:lineSpacingExtra="4dp"
        android:textSize="16sp" />

    <!-- pusty element z wagą spycha stopkę na dół ekranu (lekcja 02) -->
    <View
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <TextView
        android:id="@+id/tvStopka"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="1"
        android:textSize="14sp" />

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

import android.graphics.Color
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

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

        // 1. znajdujemy napisy
        val tvPrzyslowie = findViewById<TextView>(R.id.tvPrzyslowie)
        val tvZnaczenie = findViewById<TextView>(R.id.tvZnaczenie)
        val tvStopka = findViewById<TextView>(R.id.tvStopka)

        // 2. dane: dwie tablice tej samej długości
        val przyslowia = arrayOf(
            "Ćwiczenie czyni mistrza.",
            "Nie od razu Kraków zbudowano.",
            "Bez pracy nie ma kołaczy.",
            "Kto pyta, nie błądzi.",
            "Gdzie kucharek sześć, tam nie ma co jeść.",
            "Lepiej późno niż wcale."
        )
        val znaczenia = arrayOf(
            "Umiejętności zdobywa się przez powtarzanie.",
            "Duże rzeczy wymagają czasu i cierpliwości.",
            "Sukces wymaga wysiłku.",
            "Lepiej zapytać, niż zgadywać i popełnić błąd.",
            "Gdy za dużo osób zarządza jedną sprawą, nic się nie udaje.",
            "Lepiej zrobić coś z opóźnieniem, niż nie zrobić wcale."
        )

        // 3. losujemy numer: od 0 do ostatniego indeksu
        val nr = przyslowia.indices.random()
        val przyslowie = przyslowia[nr]

        // 4. tekst
        tvPrzyslowie.text = "„$przyslowie”"
        tvZnaczenie.text = znaczenia[nr]
        tvStopka.text = "Przysłowie ${nr + 1} z ${przyslowia.size}"
        tvStopka.append(" · uruchom ponownie, aby wylosować inne")

        // 5. rozmiar zależny od długości tekstu
        if (przyslowie.length > 30) {
            tvPrzyslowie.textSize = 24f
        }

        // 6. kolor zależny od numeru (liczymy od 1, jak w stopce)
        if ((nr + 1) % 2 == 0) {
            tvStopka.setTextColor(Color.parseColor("#2E7D32"))
        } else {
            tvStopka.setTextColor(Color.parseColor("#C62828"))
        }
    }
}

Co dzieje się po kolei

  • Wygląd przysłowia (krój serif, kursywa, 30sp) jest ustawiony w XML. Kod wpisuje tylko tekst i — gdy trzeba — zmienia rozmiar.
  • Dwie tablice mają tyle samo elementów, a element nr 3 w jednej pasuje do elementu nr 3 w drugiej. Jeden wylosowany numer obsługuje obie.
  • przyslowia.indices to zakres numerów tablicy (0..5), a random() losuje z niego jedną liczbę.
  • Polskie cudzysłowy „ ” są zwykłymi znakami w napisie — dookoła wstawiamy wartość zmiennej przez $przyslowie.
  • W stopce ${nr + 1} zamienia numer liczony od 0 na liczony od 1, zrozumiały dla człowieka. append dopisuje drugą część.
  • przyslowie.length to liczba znaków. Powyżej 30 zmniejszamy czcionkę do 24sp.
  • Reszta z dzielenia % 2 równa 0 oznacza liczbę parzystą.

Sprawdź trzy rzeczy

  1. Uruchom aplikację kilka razy (zamknij ją przyciskiem Wstecz i otwórz ikoną). Przysłowie się zmienia — onCreate wykonuje się przy każdym otwarciu.
  2. Na emulatorze otwórz Ustawienia → Wyświetlacz → Rozmiar czcionki i ustaw największy. Wszystkie napisy w aplikacji urosną, bo są w sp. Stopka zostanie w jednej linii z wielokropkiem.
  3. Zmień tvPrzyslowie.textSize = 24f na tvPrzyslowie.textSize = tvPrzyslowie.textSize - 6. Długie przysłowie zrobi się olbrzymie — odczyt zwraca piksele, nie sp.
ELEMENTY WBUDOWANE

Zestawienie elementów

ElementTypCo robi
android:textSize, textColor, textStyleatrybutyRozmiar, kolor, styl tekstu.
android:fontFamilyatrybutKrój: serif, monospace, sans-serif-light…
android:maxLines + ellipsizeatrybutyOgraniczenie linii i wielokropek.
android:textAllCaps, letterSpacing, lineSpacingExtraatrybutyWielkie litery, odstęp liter, odstęp linii.
tv.textwłaściwośćOdczyt i zmiana tekstu.
tv.append("…")metodaDopisuje tekst na końcu.
tv.textSize = 20fwłaściwośćRozmiar: zapis w sp, odczyt w pikselach.
tv.setTextColor(kolor)metodaKolor tekstu.
tv.setBackgroundColor(kolor)metodaKolor tła.
Color.RED, Color.parseColor("#…")IntKolor jako liczba.
getColor(R.color.…)IntKolor z colors.xml.
"$zmienna", "${wyrażenie}"szablonWstawienie wartości do napisu.
tablica.indices.random()IntLosowy poprawny numer elementu.
napis.lengthIntLiczba znaków.
CZĘSTE BŁĘDY

Zanim utkniesz

ZapisProblem
tv.text = punkty (gdy punkty to Int)Błąd kompilacji: Type mismatch. Tekst musi być napisem: "$punkty" albo punkty.toString().
tv.setText(punkty) z liczbą IntKompiluje się, ale aplikacja się zamyka (Resources$NotFoundException): liczbę Android traktuje jako numer zasobu tekstowego.
tv.textSize = 20Błąd kompilacji: oczekiwany Float. Pisz 20f.
tv.setTextColor(R.color.akcent)Dziwny kolor. Potrzebne getColor(R.color.akcent).
Color podświetlone na czerwonoBrak import android.graphics.Color — Alt+Enter.
"Wynik: $a+b"Wyświetli np. „Wynik: 3+b”. Wyrażenie musi być w klamrach: "${a + b}".
ellipsize nie działaBrak maxLines — tekst może się zawijać bez końca.
przyslowia[przyslowia.size]Awaria: ArrayIndexOutOfBoundsException. Ostatni indeks to size - 1.
ZADANIA

Zadania

Każde zadanie wykonaj w nowym projekcie Empty Views Activity. Cały kod pisz w onCreate. Wskazówkę otwórz dopiero wtedy, gdy utkniesz.

ZAD 1Galeria stylów★☆☆

Ekran z dziesięcioma napisami „Android”, każdy z innym ustawieniem: rozmiar 12sp i 36sp, pogrubienie, kursywa, pogrubienie z kursywą, krój serif, krój monospace, kolor czerwony, białe litery na czarnym tle, odstęp liter 0.3. Wszystko w XML, bez kodu.

pokaż wskazówkę
  • Pogrubienie z kursywą: android:textStyle="bold|italic".
ZAD 2Wizytówka z kodu★☆☆

W kodzie zadeklaruj zmienne imie, nazwisko, rokUrodzenia. Na ekranie mają się pojawić trzy napisy: „Anna Nowak”, „Rok urodzenia: 2009”, „Wiek w tym roku: 17”. Wiek oblicz w kodzie (rok bieżący wpisz na stałe).

pokaż wskazówkę
  • "Wiek w tym roku: ${2026 - rokUrodzenia}" — obliczenie w klamrach.
ZAD 3Lista nagłówków wiadomości★☆☆

Pięć „wiadomości” jedna pod drugą: każda ma pogrubiony tytuł w jednej linii i treść ograniczoną do dwóch linii z wielokropkiem. Teksty niech będą na tyle długie, żeby wielokropek było widać.

pokaż wskazówkę
  • Tytuł: maxLines="1" + ellipsize="end". Treść: maxLines="2" + ellipsize="end".
ZAD 4Losowa ocena★★☆

Aplikacja losuje ocenę od 1 do 6 i pokazuje ją bardzo dużą cyfrą (96sp) na środku ekranu, a pod nią słownie („celujący”, „bardzo dobry”…). Kolor cyfry: 1 — czerwony, 2–3 — pomarańczowy, 4–5 — niebieski, 6 — zielony. Kolory zdefiniuj w colors.xml.

pokaż wskazówkę
  • Losowanie: (1..6).random(). Wybór koloru i słowa wygodnie zrobić instrukcją when (ocena) { 1 -> … 2, 3 -> … }. Kolor z zasobów: getColor(R.color.zielony).
ZAD 5Tabliczka mnożenia★★☆

Jeden TextView z czcionką monospace. Kod w pętli dopisuje do niego tabliczkę mnożenia przez losową liczbę od 2 do 9: „7 x 1 = 7”, „7 x 2 = 14”… do 10, każda w osobnej linii. Nad nią nagłówek „Tabliczka mnożenia przez 7”.

pokaż wskazówkę
  • Najpierw tv.text = "", potem w pętli for (i in 1..10) wywołuj tv.append("$liczba x $i = ${liczba * i}\n").
ZAD 6Statystyki tekstu★★★

W kodzie jest długi napis — na przykład pierwszy akapit dowolnego opowiadania (wpisz go sam). Aplikacja pokazuje: cały tekst w napisie z przewijaniem (ScrollView z lekcji 03), a pod nim statystyki: liczbę znaków, liczbę słów, liczbę samogłosek i najdłuższe słowo. Liczba samogłosek ma kolor zielony, gdy stanowi więcej niż 35% znaków, w przeciwnym razie czerwony.

pokaż wskazówkę
  • Słowa: tekst.split(" "). Samogłoski: tekst.count { it.lowercaseChar() in "aąeęioóuy" }. Najdłuższe słowo: slowa.maxBy { it.length }.
PODSUMOWANIE

Co trzeba zapamiętać

  • Wygląd napisu ustawiaj w XML: textSize (sp), textColor, textStyle, fontFamily.
  • Zbyt długi tekst utnij parą maxLines + ellipsize="end".
  • W kodzie: tv.text = "Wynik: $x", tv.append(…), tv.textSize = 20f.
  • Kolor z kodu: setTextColor(Color.parseColor("#…")) lub setTextColor(getColor(R.color.…)) — nigdy samo R.color.….
  • Do text przypisuj napis, nie liczbę.

Dokumentacja: TextView, Szablony napisów w Kotlinie.

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