Adaptive Layout: klíčové pojmy, třídy velikostí a kvalifikátory

Autor: IT Sectr Publikováno: 2026-02-26 Doba čtení: 10 min

Adaptive Layout — přístup k tvorbě rozhraní, při kterém aplikace používá různé rozvržení pro různé typy zařízení a orientace obrazovky. Na rozdíl od responsive designu adaptive layout přepíná mezi předem připravenými rozvrženími v bodech breakpoint. Článek rozebírá Size Classes a UITraitCollection v iOS, kvalifikátory sw600dp/layout-w600dp v Androidu a uvádí praktické příklady.

Hlavní body

  • Adaptive Layout — diskrétní přepínání rozvržení v závislosti na velikosti obrazovky, orientaci a typu zařízení
  • Size Classes v iOS klasifikují prostor jako Compact nebo Regular horizontálně a vertikálně
  • UITraitCollection — kontejner charakteristik prostředí iOS (velikost, měřítko, force touch, barevný gamut)
  • sw600dp — Android kvalifikátor minimální šířky pro tablety (7" a více)
  • layout-w600dp — kvalifikátor dostupné šířky, který se aktivuje při dostatečném prostoru v aktuální orientaci

Co je Adaptive Layout?

Adaptive Layout — strategie vytváření rozhraní, při které vývojář vytváří samostatná rozvržení pro každý typ zařízení a přepíná mezi nimi na základě charakteristik obrazovky. Na rozdíl od responsive designu, kde prvky plynule přecházejí, adaptive layout používá diskrétní přepínání: telefon — jedno rozvržení, tablet — jiné, desktop — třetí.

Apple zavedl Size Classes v iOS 8 (2014) spolu s univerzálními aplikacemi (universal binaries fungujícími na iPhone i iPad). Google představil kvalifikátor smallestWidth (swdp) v Android 3.2 (2011). Oba mechanismy řeší stejný problém: poskytnout vývojáři nástroj pro vytváření různých UI pro různé obrazovky bez duplikace kódu.

Moderní doporučení Apple HIG a Google Material Design se shodují, že adaptive layout je povinný pro aplikace podporující více než jednu velikost obrazovky. Google Play označuje chybějící adaptaci pro tablety jako nedostatek. App Store nemá formální požadavek, ale uživatelé iPadu očekávají nativní zážitek, ne nataženou aplikaci pro iPhone.

Size Classes a UITraitCollection v iOS

Size Classes — charakteristika iOS definující dostupný prostor jako Compact nebo Regular na každé ose. UITraitCollection — systém iOS pro předávání charakteristik prostředí přes hierarchii view: velikost, měřítko obrazovky, force touch capability, barevný gamut (light/dark), accessibility settings.

Zařízení / OrientaceHorizontalVertical
iPhone portrét (všechny modely)CompactRegular
iPhone Plus/Pro Max na šířkuRegularCompact
iPhone SE / mini na šířkuCompactCompact
iPad portrétRegularRegular
iPad na šířkuRegularRegular
iPad Split View (1/3 obrazovky)CompactRegular

UITraitCollection je tvořen systémem a předáván od UIApplication přes UIWindow ke každému UIView. Při změně orientace nebo velikosti okna (Split View) systém vygeneruje nový UITraitCollection a zavolá traitCollectionDidChange. Ve SwiftUI jsou změny sledovány přes Environment Values a automaticky překreslují view.

Příklad adaptivního rozvržení ve Swift

Adaptace přes UITraitCollection v UIKit je implementována přihlášením k odběru změn trait collection a přestavbou rozvržení. Níže uvedený příklad ukazuje kontroler, který přepíná mezi vertikálním stackem pro iPhone a split rozvržením pro iPad.

swift
// Adaptivní kontroler s Size Classes
import UIKit

final class AdaptiveViewController: UIViewController {

    private let compactStack = UIStackView()
    private let regularStack = UIStackView()
    private let sidebar = UIView()
    private let content = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        updateLayout(for: traitCollection)
    }

    override func traitCollectionDidChange(
        _ previousTraitCollection: UITraitCollection?
    ) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.horizontalSizeClass
            != previousTraitCollection?.horizontalSizeClass {
            updateLayout(for: traitCollection)
        }
    }

    private func updateLayout(for traits: UITraitCollection) {
        if traits.horizontalSizeClass == .regular {
            showRegularLayout() // iPad: postranní panel + obsah
        } else {
            showCompactLayout() // iPhone: panel karet + push
        }
    }

    private func showRegularLayout() {
        view.subviews.forEach { $0.removeFromSuperview() }
        regularStack.addArrangedSubview(sidebar)
        regularStack.addArrangedSubview(content)
        regularStack.frame = view.bounds
        regularStack.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(regularStack)
    }

    private func showCompactLayout() {
        view.subviews.forEach { $0.removeFromSuperview() }
        compactStack.addArrangedSubview(content)
        compactStack.frame = view.bounds
        compactStack.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(compactStack)
    }

    private func setupViews() {
        sidebar.backgroundColor = .systemGray6
        content.backgroundColor = .systemBackground
        compactStack.axis = .vertical
        regularStack.axis = .horizontal
    }
}

Metoda traitCollectionDidChange je volána při každé změně traits, ale kontrolujeme pouze horizontalSizeClass — nejvýznamnější indikátor pro změnu rozvržení. V iOS 17+ se doporučuje používat UIViewController.horizontalSizeClass jako computed property pro reaktivní aktualizaci bez přihlášení k odběru změn.

Android kvalifikátory: sw600dp a w600dp

Android poskytuje dva hlavní kvalifikátory šířky: swdp (smallestWidth) a wdp (available width). Rozdíl je zásadní: sw — minimální šířka obrazovky nezávisle na orientaci, w — dostupná šířka s ohledem na aktuální orientaci. sw zaručuje, že se rozvržení načte pro zařízení, které fyzicky má uvedenou minimální šířku. w reaguje na otočení — v režimu na šířku může aktivovat w600dp, i když je na výšku šířka 360 dp.

KvalifikátorPodmínkaPříklad zařízení
layout-sw600dpMinimální šířka ≥ 600 dpiPad (768 dp), Pixel C (900 dp)
layout-w600dpAktuální šířka ≥ 600 dpiPad v Split View (600 dp), telefon na šířku
layout-landOrientace na šířkuJakékoli zařízení otočené horizontálně
layout-sw720dpMinimální šířka ≥ 720 dpiPad Pro (833 dp), Galaxy Tab S9 (800 dp)

Hierarchie zdrojů v Androidu: res/layout/activity_main.xml (telefon), res/layout-sw600dp/activity_main.xml (tablet 7"), res/layout-w600dp-land/activity_main.xml (telefon na šířku). Android vybírá nejkonkrétnější kvalifikátor odpovídající aktuální konfiguraci zařízení. Při neexistenci vhodného souboru se použije základní zdroj z res/layout/.

Příklad adaptivního rozvržení v Kotlin

Moderní vývoj pro Android používá Jetpack WindowManager k určení velikosti okna namísto přímého čtení zdrojů. To je důležité zejména pro skládací zařízení, kde se velikost obrazovky může dynamicky měnit (Galaxy Fold se rozkládá z 6,2" na 7,6").

kotlin
// Adaptace přes Jetpack WindowManager
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun AdaptiveScreen() {
    val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass

    FlowRow(
        verticalAlignment = Arrangement.Top,
        horizontalArrangement = when (windowSizeClass.windowWidthSizeClass) {
            WindowWidthSizeClass.EXPANDED -> Arrangement.SpaceEvenly
            else -> Arrangement.Start
        }
    ) {
        when (windowSizeClass.windowWidthSizeClass) {
            WindowWidthSizeClass.COMPACT -> {
                CompactContent()
            }
            WindowWidthSizeClass.MEDIUM -> {
                MediumContent()
            }
            WindowWidthSizeClass.EXPANDED -> {
                ExpandedContent()
            }
        }
    }
}

@Composable
private fun CompactContent() {
    Column(modifier = Modifier.padding(16.dp)) {
        Text("Telefon", style = MaterialTheme.typography.headlineSmall)
        ListContent()
    }
}

@Composable
private fun MediumContent() {
    Row(modifier = Modifier.padding(24.dp)) {
        NavigationRail { ... }
        Column { ListContent() }
    }
}

@Composable
private fun ExpandedContent() {
    Row(modifier = Modifier.padding(32.dp)) {
        PermanentNavigationDrawer { ... }
        Column {
            ListContent()
        }
        DetailPane()
    }
}

Komponenta currentWindowAdaptiveInfo() z knihovny androidx.window přizpůsobuje rozhraní libovolnému zařízení: telefon, tablet, skládací, ChromeOS. Třídy šířky: COMPACT (0–600 dp), MEDIUM (600–840 dp), EXPANDED (>840 dp). Třídy výšky: COMPACT (0–480 dp), MEDIUM (480–900 dp), EXPANDED (>900 dp).

Adaptive Layout ve SwiftUI

SwiftUI poskytuje vestavěné nástroje pro adaptivní rozvržení bez přímého použití Size Classes. AnyLayout, ViewThatFits a GeometryReader umožňují vytvářet rozhraní, která se automaticky přizpůsobují dostupnému prostoru.

swift
// Adaptace SwiftUI přes AnyLayout a ViewThatFits
import SwiftUI

struct AdaptiveGrid: View {
    @Environment(\.horizontalSizeClass) private var hSizeClass

    var body: some View {
        let layout = hSizeClass == .regular
            ? AnyLayout(HStackLayout())
            : AnyLayout(VStackLayout())

        layout {
            Label("Oblíbené", systemImage: "star")
            Label("Nedávné", systemImage: "clock")
            Label("Nastavení", systemImage: "gear")
        }
        .padding()
    }
}

// ViewThatFits — automatický výběr rozvržení
struct SmartLayout: View {
    var body: some View {
        ViewThatFits {
            HStack { // Priorita 1: horizontální
                CardView()
                CardView()
            }
            VStack { // Pokud se nevejde — vertikální
                CardView()
                CardView()
            }
        }
    }
}

ViewThatFits — výkonný nástroj SwiftUI, který automaticky vybírá první podřízený view, který se vejde do dostupného prostoru bez oříznutí. To eliminuje potřebu explicitní kontroly Size Classes pro jednoduchá adaptivní přepínání. AnyLayout umožňuje změnit typ rozvržení (HStack/VStack) bez if-else v těle view.

Adaptive Layout v Jetpack Compose

Jetpack Compose používá WindowSizeClass (z knihovny Material 3 adaptive) a BoxWithConstraints pro adaptivní rozvržení. Na rozdíl od XML kvalifikátorů Compose určuje velikost okna za běhu a reaktivně překresluje UI při změně konfigurace.

kotlin
// Adaptace Jetpack Compose přes BoxWithConstraints
@Composable
fun AdaptiveList(items: List<String>) {
    BoxWithConstraints {
        val width = maxWidth

        if (width >= 600.dp) {
            // Tablet: dva sloupce (list-detail)
            Row(modifier = Modifier.fillMaxSize()) {
                LazyColumn(modifier = Modifier.weight(1f)) {
                    items(items) { item ->
                        ListItem(text = item)
                    }
                }
                var selected by remember { mutableStateOf(items.first()) }
                DetailPanel(item = selected)
                    .weight(2f)
            }
        } else {
            // Telefon: jeden sloupec s navigací
            LazyColumn(modifier = Modifier.fillMaxSize()) {
                items(items) { item ->
                    ListItem(text = item, onClick = { navigateToDetail(item) })
                }
            }
        }
    }
}

@Composable
fun AdaptiveListMaterial3() {
    val windowClass = currentWindowAdaptiveInfo().windowSizeClass

    AdaptiveLayout(
        layout = windowClass.windowWidthSizeClass
    ) {
        when (windowClass.windowWidthSizeClass) {
            WindowWidthSizeClass.COMPACT -> {
                ListDetailScaffold(
                    isDetailOnly = false,
                    list = { ListPane() },
                    detail = { DetailPane() }
                )
            }
            else -> {
                ListDetailScaffold(
                    isDetailOnly = false,
                    list = { ListPane() },
                    detail = { DetailPane() }
                )
            }
        }
    }
}

Material 3 Adaptive Layouts poskytuje hotové komponenty: ListDetailScaffold, SupportingPaneScaffold, NavigationSuiteScaffold. Tyto komponenty se automaticky přizpůsobují WindowWidthSizeClass — přepínají mezi stacked (COMPACT) a side-by-side (MEDIUM/EXPANDED). Vývojář stačí vybrat vzor a předat obsahové panely.

Často kladené otázky

Jaký je rozdíl mezi sw600dp a w600dp?

sw600dp (smallestWidth) — minimální šířka obrazovky nezávisle na orientaci. Vždy funguje na tabletech 7"+. w600dp (available width) — dostupná šířka s ohledem na aktuální orientaci. Funguje na telefonech na šířku, kde šířka může přesáhnout 600 dp.

Co je UITraitCollection v iOS?

UITraitCollection — iOS objekt obsahující charakteristiky prostředí: size classes (horizontal/vertical), display scale, force touch capability, user interface idiom (iPhone/iPad), color gamut, accessibility settings. Je předáván od UIApplication přes hierarchii view a mění se při změně orientace nebo velikosti okna.

Jak přizpůsobit aplikaci pro skládací zařízení?

Použijte Jetpack WindowManager (Android) a UIScreen nativeBounds + traitCollection (iOS). Skládací zařízení mění Size Class při rozložení. Doporučuje se architektura založená na kanonických rozvrženích (list-detail, supporting pane) s reaktivním přihlášením ke změnám velikosti okna bez restartování Activity.

Je nutné vytvářet samostatné storyboardy pro iPad?

Ne. Použijte jeden storyboard s Size Classes variacemi constraintů nebo programové rozvržení přes UIKit. SwiftUI storyboardy vůbec nevyžaduje. Samostatné storyboardy pro iPad vytvářejí duplicitu a komplikují údržbu — je lepší přizpůsobit jedno rozvržení přes Size Classes.

Co jsou canonical layouts v Material 3?

Canonical layouts — hotové vzory adaptivního rozvržení od Google: list-detail (seznam + podrobnosti), supporting pane (obsah + panel akcí), feed (karty). Každý vzor podporuje tři stavy (compact/medium/expanded) a je implementován v knihovně Material 3 Adaptive přes ListDetailScaffold a SupportingPaneScaffold.

Shrnutí

  • Adaptive Layout — diskrétní přepínání rozvržení v bodech breakpoint pro různá zařízení
  • Size Classes iOS (Compact/Regular) určují rozvržení pro iPhone, iPad a Split View
  • UITraitCollection — mechanismus předávání charakteristik prostředí přes hierarchii view
  • sw600dp — Android kvalifikátor minimální šířky pro tablety 7"+
  • w600dp — kvalifikátor dostupné šířky aktivovaný při otočení na šířku
  • Jetpack WindowManager poskytuje WindowSizeClass (WindowWidthSizeClass: COMPACT/MEDIUM/EXPANDED)
  • Material 3 Adaptive — hotové komponenty s automatickou adaptací (ListDetailScaffold)

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é