ParagraphStyle — klíčové pojmy, vlastnosti a použití

Autor: IT Sectr Publikováno: 2026-07-25 Doba čtení: 10 min

ParagraphStyle — je sada parametrů formátování, která určuje vizuální vzhled odstavce textu. V mobilním vývoji ParagraphStyle zahrnuje zarovnání (left, center, right, justified), řádkování, odsazení prvního řádku, mezery mezi odstavci a směr textu. Podle Material Design Typography Guidelines (2025) zajišťuje konzistentní používání ParagraphStyle na všech obrazovkách aplikace jednotný typografický rytmus a snižuje vizuální šum při přepínání mezi sekcemi.

Hlavní

  • ParagraphStyle — objekt nastavení formátování odstavce: zarovnání, odsazení, mezery.
  • Platformy — iOS: NSMutableParagraphStyle, Android: ParagraphStyle (Compose) / Layout (View), Flutter: TextStyle.
  • Zarovnání — left pro hlavní text, center pro nadpisy, justified pro knižní formát.
  • Odsazení — firstLineHeadIndent (odsazení prvního řádku), paragraphSpacing (mezera mezi odstavci).
  • Lokalizace — ParagraphStyle zohledňuje směr textu (LTR/RTL) pro různé jazyky.

Co je ParagraphStyle v typografii

ParagraphStyle (styl odstavce) — je soubor pravidel formátování aplikovaných na jeden nebo více odstavců textu. Na rozdíl od znakových stylů (bold, italic, font-size), které pracují na úrovni jednotlivých znaků, ParagraphStyle spravuje makro-vlastnosti: umístění textu v kontejneru, vzdálenosti mezi řádky a odstavci, směr psaní a pravidla dělení.

Historicky pojem ParagraphStyle pochází z desktopových publikačních systémů (QuarkXPress, PageMaker, InDesign), kde každý odstavec měl svou vlastní sadu parametrů. V mobilním vývoji se tento přístup transformoval do programových API: NSMutableParagraphStyle na iOS, třídy ParagraphStyle a LineBreakStyle v Android, a také parametry jako textAlign a textHeightBehavior ve Flutter. Všechny řeší stejný úkol — správa formátování odstavců pomocí kódu, bez vázání na konkrétní textový engine.

Podle Bringhurst — The Elements of Typographic Style (2024) je správná konfigurace ParagraphStyle základem typografické kultury rozhraní. Zatímco písmo a velikost odpovídají za „hlas" textu, styl odstavce odpovídá za jeho „dech": rytmus, pauzy a akcenty. V mobilních rozhraních, kde je prostor omezený, umožňuje správný ParagraphStyle umístit více informací bez ztráty čitelnosti.

Hlavní vlastnosti ParagraphStyle

ParagraphStyle zahrnuje několik skupin vlastností, z nichž každá odpovídá za určitý aspekt formátování. Podívejme se na klíčové parametry dostupné v mobilních API. Zarovnání (alignment) — hlavní parametr určující horizontální polohu textu. Na iOS je k dispozici NSTextAlignment, v Android — Layout.Alignment, ve Flutter — TextAlign.

VlastnostiOS (NSMutableParagraphStyle)Android (Compose)Flutter (TextStyle)
ZarovnáníalignmenttextAligntextAlign
Levé odsazeníheadIndenttextIndent (v Compose)
Pravé odsazenítailIndent
Odsazení prvního řádkufirstLineHeadIndenttextIndent (firstLine)
Mezera mezi odstavciparagraphSpacingparagraphStyle (lineHeight)
Mezera před odstavcemparagraphSpacingBefore
Směr textubaseWritingDirectionTextDirection (Compose)textDirection
Režim zalomení řádkulineBreakModeoverflow (TextStyle)overflow (TextStyle)

Je důležité pochopit, že ne všechny vlastnosti jsou dostupné na všech platformách ve stejném rozsahu. Například odsazení prvního řádku (firstLineHeadIndent) je plně podporováno pouze v iOS přes NSMutableParagraphStyle. V Android se pro tento účel používá SpannableString s LeadingMarginSpan, a ve Flutter — RichText s vlastním TextSpan a paddingem. Při vývoji napříč platformami (Flutter, React Native) je třeba některé vlastnosti ParagraphStyle emulovat pomocí kontejnerů nebo Spacer.

ParagraphStyle v iOS: NSMutableParagraphStyle

V iOS je hlavním nástrojem pro práci se stylem odstavce třída NSMutableParagraphStyle — potomek NSParagraphStyle. Poskytuje úplnou sadu vlastností pro správu formátování odstavců a aplikuje se přes NSAttributedString. NSMutableParagraphStyle se používá nejen v UILabel a UITextView, ale také v Core Text přes CTParagraphStyle.

swift
// iOS: úplná konfigurace ParagraphStyle
let paragraphStyle = NSMutableParagraphStyle()

// Zarovnání
paragraphStyle.alignment = .justified     // justified

// Odsazení
paragraphStyle.headIndent = 16          // levé odsazení
paragraphStyle.tailIndent = -16         // pravé odsazení (záporné)
paragraphStyle.firstLineHeadIndent = 32 // odsazení prvního řádku

// Mezera mezi odstavci
paragraphStyle.paragraphSpacing = 12    // za odstavcem
paragraphStyle.paragraphSpacingBefore = 8 // před odstavcem

// Výška řádku
paragraphStyle.minimumLineHeight = 24
paragraphStyle.maximumLineHeight = 24

let attributes: [NSAttributedString.Key: Any] = [
    .font: UIFont.systemFont(ofSize: 16),
    .paragraphStyle: paragraphStyle
]

let label = UILabel()
label.attributedText = NSAttributedString(
    string: "This paragraph has a custom ParagraphStyle.\n\nSecond paragraph with 12 pt spacing.",
    attributes: attributes
)

V SwiftUI neexistuje přímý ekvivalent NSMutableParagraphStyle — místo toho se používá kombinace modifikátorů: .multilineTextAlignment() pro zarovnání, .lineSpacing() pro řádkování. Pro odsazení prvního řádku a mezery mezi odstavci ve SwiftUI je třeba použít Text + padding nebo AttributedString (dostupný od iOS 15+).

swift
// SwiftUI: AttributedString s ParagraphStyle (iOS 15+)
var attributed: AttributedString = """
This is the first paragraph with indent.

This is the second paragraph with 12 pt spacing.
"""

let ps = NSMutableParagraphStyle()
ps.paragraphSpacing = 12
ps.firstLineHeadIndent = 20

let container = AttributeContainer()
    .paragraphStyle(ps)

attributed.mergeAttributes(container)

Text(attributed)
    .font(.body)

Podle Apple — Text Programming Guide (2025) podporuje NSMutableParagraphStyle až 14 různých parametrů formátování. Je důležité si pamatovat, že tailIndent se nastavuje jako záporná hodnota vůči šířce kontejneru, zatímco headIndent — jako kladná. Toto neintuitivní chování často vede k chybám u začínajících iOS vývojářů.

ParagraphStyle v Android: View-systém a Compose

V Android se přístup k ParagraphStyle liší mezi View-systémem a Jetpack Compose. V klasickém View-systému se parametry odstavce nastavují přes XML atributy TextView (android:textAlignment, android:lineSpacingExtra) nebo přes SpannableString s implementacemi rozhraní ParagraphStyle z balíčku android.text.style.

kotlin
// Android View systém: ParagraphStyle přes SpannableString
val text = "First paragraph with settings.\n\nSecond paragraph."
val spannable = SpannableString(text)

// Zarovnání do bloku
spannable.setSpan(
    AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
    0, text.length,
    Spannable.SPAN_PARAGRAPH
)

// Odsazení prvního řádku přes LeadingMarginSpan
spannable.setSpan(
    LeadingMarginSpan.Standard(0, 20),
    0, text.indexOf('\n'),
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)

textView.text = spannable

V Jetpack Compose je ParagraphStyle spravován přes parametry TextStyle. Pro zarovnání se používá textAlign, pro řádkování — lineHeight (v sp nebo em), pro odsazení prvního řádku — textIndent. Compose také podporuje LineBreak pro jemné řízení dělení (Simple, Heading, Paragraph), což je užitečné zejména pro vícejazyčný text.

kotlin
// Jetpack Compose: ParagraphStyle přes TextStyle
Text(
    text = "První odstavec s vlastním stylem.\n\nDruhý odstavec s odsazením.",
    style = TextStyle(
        textAlign = TextAlign.Justify,
        lineHeight = 24.sp,
        textIndent = TextIndent(firstLine = 16.sp),
        lineBreak = LineBreak.Paragraph
    )
)

Podle Android Developers — Compose ParagraphStyle (2025) je při použití TextIndent v Compose důležité nastavit firstLine v sp (ne v dp), protože odsazení prvního řádku by se mělo škálovat spolu s textem. Pokud je odsazení nastaveno v dp, při zvětšení velikosti písma se odsazení prvního řádku vizuálně zmenší, což naruší typografické proporce.

ParagraphStyle ve Flutter: TextHeightBehavior a StrutStyle

Ve Flutter není paradigma ParagraphStyle vyčleněno do samostatné třídy — místo toho se používá kombinace parametrů TextStyle a doplňkových tříd. Zarovnání se nastavuje přes TextAlign, řádkování — přes height (bez jednotky), a TextHeightBehavior spravuje viditelná odsazení prvního a posledního řádku.

dart
// Flutter: ParagraphStyle přes parametry Text
Text(
    'Stylovaný odstavec ve Flutter.\n\nDruhý odstavec s odsazením.',
    style: TextStyle(
        fontSize: 16,
        height: 1.5,
        leadingDistribution: TextLeadingDistribution.proportional,
    ),
    textAlign: TextAlign.justify,
    textHeightBehavior: TextHeightBehavior(
        applyHeightToFirstAscent: true,
        applyHeightToLastDescent: true,
    ),
)

Pro složitější scénáře Flutter nabízí použití RichText s vlastním TextSpan a WidgetSpan. To umožňuje kombinovat text s inline widgety (ikony, obrázky) v jednom odstavci při zachování jednotných pravidel formátování. Tento přístup však vyžaduje ruční správu dělení a nepodporuje automatické nastavování dělení.

dart
// Flutter: RichText s vlastním formátováním odstavce
RichText(
    text: TextSpan(
        style: TextStyle(fontSize: 16, height: 1.5),
        children: [
            TextSpan(text: 'First paragraph with icon '),
            WidgetSpan(
                child: Icon(Icons.star, size: 16),
                alignment: PlaceholderAlignment.middle,
            ),
            TextSpan(text: '\n\nSecond paragraph after spacing.'),
        ],
    ),
)

Podle Flutter Documentation — Text Widget (2025) je TextHeightBehavior klíčový parametr pro správné zobrazení ParagraphStyle ve Flutter. Pokud je applyHeightToFirstAscent nastaveno na false, horní odsazení prvního řádku je ignorováno a text „přilne" k hornímu okraji kontejneru. To je užitečné pro nadpisy, ale nežádoucí pro hlavní text.

ParagraphStyle a lokalizace: LTR/RTL a regionální zvláštnosti

ParagraphStyle musí zohledňovat směr psaní pro každou lokalizaci. V mobilních aplikacích s podporou arabštiny, hebrejštiny nebo urdštiny (psaní zprava doleva, RTL) by se odsazení a zarovnání měla zrcadlově měnit. iOS podporuje automatické přepínání přes baseWritingDirection = .natural, Android — přes TextDirection, Flutter — přes textDirection.

Nastavení zarovnání pro RTL lokalizace vyžaduje zvláštní pozornost. Pokud v režimu LTR headIndent nastavuje levé odsazení, v RTL se automaticky stává pravým. Ne všechny implementace však tento přechod při explicitním nastavení zarovnání (NSTextAlignment.left místo NSTextAlignment.natural) správně zpracovávají. Podle Google Internationalization Guide (2025) pro vícejazyčné aplikace vždy používejte natural alignment a kontrolujte odsazení v obou rozvrženích.

kotlin
// Android: RTL podpora v ParagraphStyle
val textView = TextView(context)

// Povolit automatickou RTL podporu
textView.textDirection = View.TEXT_DIRECTION_LOCALE
textView.textAlignment = View.TEXT_ALIGNMENT_TEXT_START

// Spannable s RTL podporou
val spannable = SpannableString(arabicText)
spannable.setSpan(
    AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
    0, arabicText.length,
    Spannable.SPAN_PARAGRAPH
)

Regionální zvláštnosti také zahrnují různá pravidla pro odsazení prvního řádku. V evropské typografii je odsazení prvního řádku (firstLineHeadIndent) standardem pro zvýraznění odstavce. V japonské a čínské typografii se odsazení prvního řádku také používá, ale jeho velikost se může lišit (obvykle 1 em oproti 1.5 em v evropské tradici). V arabské typografii je odsazení prvního řádku vzácné, odstavce se častěji oddělují svislou mezerou.

Typické chyby při práci s ParagraphStyle

Nejčastější chyba — používání ParagraphStyle pouze přes globální atributy textového pole bez zohlednění různého formátování jednotlivých odstavců. V UILabel nebo TextView s více odstavci oddělenými \n se ParagraphStyle aplikuje na celý text stejně, pokud se nepoužije attributed-text s různými styly pro každý odstavec.

  • Ignorování paragraphSpacingBefore — mnoho vývojářů nastavuje paragraphSpacing, ale zapomíná na paragraphSpacingBefore. Pro první odstavec v bloku umožňuje paragraphSpacingBefore nastavit mezeru shora bez vytváření dalšího kontejneru. To je užitečné zejména pro seznamy s nadpisy.
  • Pevné zarovnání (left/right) místo natural — pokud aplikace podporuje RTL lokalizace, použití NSTextAlignment.left nebo TextAlign.Start místo natural vede k nesprávnému zobrazení v arabských a hebrejských lokalizacích.
  • Chybějící kontrola zalomení (line break mode) — v úzkých kontejnerech (seznamy, sidebar) vede nesprávný lineBreakMode k ořezávání slov. Používejte byWordWrapping a kontrolujte dlouhá slova v kontextu konkrétní lokalizace.
  • Míchání Spannable s různými ParagraphStyle — při nastavování Spannable s SPAN_PARAGRAPH je důležité správně vypočítat hranice odstavců. Nesoulad počáteční/koncové pozice se skutečnými hranicemi odstavce vede k ignorování stylu.
  • Zapomenuté zarovnání baseline — při použití ParagraphStyle s pevným lineHeight (minimumLineHeight) se ujistěte, že je zapnuto zarovnání textu na baseline. V iOS k tomu slouží label.baselineAdjustment = .alignBaselines.

Podle UX Collective — Common Typography Bugs in Mobile Apps (2025) tvoří problémy s ParagraphStyle 18 % všech typografických chyb v mobilních aplikacích. Nejkritičtější jsou případy, kdy nesprávný paragraphSpacing vede k překrývání textu na různých řádcích nebo kdy se RTL lokalizace zobrazují s LTR odsazením. Doporučuje se vytvářet unit testy pro každý parametr ParagraphStyle s testovacími řetězci v různých jazycích.

Často kladené otázky

Čím se ParagraphStyle liší od TextStyle v iOS?

NSMutableParagraphStyle spravuje formátování odstavce (zarovnání, odsazení, řádkování), zatímco TextStyle spravuje atributy znaků (písmo, barva, velikost). Oba se aplikují přes NSAttributedString. ParagraphStyle působí na úrovni odstavce, TextStyle na úrovni znaků. Několik TextStyle může být v jednom odstavci, ale ParagraphStyle — pouze jeden na odstavec.

Jak nastavit odsazení prvního řádku v Jetpack Compose?

V Jetpack Compose se odsazení prvního řádku nastavuje přes TextIndent uvnitř TextStyle: TextStyle(textIndent = TextIndent(firstLine = 16.sp)). Hodnota musí být v sp, aby se škálovala s textem. Pro víceřádkový text se odsazení aplikuje na každý řádek začínající nový odstavec (znak \n). Pro první odstavec se odsazení aplikuje vždy.

Jak nakonfigurovat mezeru mezi odstavci ve SwiftUI?

Ve SwiftUI neexistuje přímý ekvivalent paragraphSpacing. Pro mezeru mezi odstavci použijte AttributedString (iOS 15+) s NSMutableParagraphStyle a vlastností paragraphSpacing. Nebo oddělujte odstavce přes Text("...\n\n...") a přidávejte .padding() mezi textové bloky. Pro složité typografické scénáře použijte NSAttributedString přes UILabelRepresentable.

Proč paragraphSpacing nefunguje v Android TextView?

TextView v Android nemá vlastnost paragraphSpacing — nastavuje se přes SpannableString s LeadingMarginSpan nebo vlastním LineBackgroundSpan. Pro řádkování použijte setLineSpacing, pro mezeru mezi odstavci — oddělujte odstavce dalším \n nebo použijte složený kontejner z několika TextView.

Jak ParagraphStyle ovlivňuje přístupnost mobilní aplikace?

Správný ParagraphStyle zlepšuje přístupnost: dostatečný paragraphSpacing pomáhá uživatelům s kognitivními poruchami lépe rozlišovat hranice odstavců. WCAG 2.2 doporučuje vizuální oddělování odstavců (odsazení nebo mezera). paragraphSpacing by neměl být menší než 1.5 × line-height. Pro RTL lokalizace zkontrolujte, zda se odsazení zobrazují zrcadlově.

Shrnutí

  • ParagraphStyle — sada pravidel formátování odstavce: zarovnání, odsazení, mezery mezi řádky a odstavci.
  • iOS — NSMutableParagraphStyle se 14+ parametry, aplikuje se přes NSAttributedString; ve SwiftUI — AttributedString (iOS 15+).
  • Android View — SpannableString s implementacemi ParagraphStyle (AlignmentSpan, LeadingMarginSpan).
  • Android Compose — TextStyle.textAlign, lineHeight, textIndent a LineBreak pro správu dělení.
  • Flutter — kombinace TextStyle.height, TextAlign, TextHeightBehavior a StrutStyle pro fixaci výšky řádku.
  • Lokalizace — používejte natural alignment pro podporu RTL lokalizací; kontrolujte odsazení v obou rozvrženích.
  • Typické chyby — pevné zarovnání místo natural, chybějící paragraphSpacingBefore, nesprávný lineBreakMode pro úzké kontejnery.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také