Adaptive Layout: konsep kunci, kelas ukuran dan kualifikator

Penulis: IT Sectr Diterbitkan: 2026-02-26 Waktu membaca: 10 mnt

Adaptive Layout — pendekatan dalam merancang antarmuka di mana aplikasi menggunakan tata letak yang berbeda untuk berbagai jenis perangkat dan orientasi layar. Berbeda dengan responsive design, adaptive layout beralih di antara tata letak yang sudah disiapkan sebelumnya di titik-titik breakpoint. Artikel ini membahas Size Classes dan UITraitCollection di iOS, kualifikator sw600dp/layout-w600dp di Android, dan memberikan contoh praktis.

Poin Utama

  • Adaptive Layout — perpindahan diskrit tata letak tergantung pada ukuran layar, orientasi, dan jenis perangkat
  • Size Classes di iOS mengklasifikasikan ruang sebagai Compact atau Regular secara horizontal dan vertikal
  • UITraitCollection — wadah karakteristik lingkungan iOS (ukuran, skala, force touch, gamut warna)
  • sw600dp — kualifikator lebar minimum Android untuk tablet (7" dan lebih besar)
  • layout-w600dp — kualifikator lebar tersedia yang aktif ketika ada cukup ruang di orientasi saat ini

Apa itu Adaptive Layout?

Adaptive Layout — strategi membangun antarmuka di mana pengembang membuat tata letak terpisah untuk setiap jenis perangkat dan beralih di antara mereka berdasarkan karakteristik layar. Berbeda dengan responsive design, di mana elemen mengalir secara mulus, adaptive layout menggunakan perpindahan diskrit: telepon — satu tata letak, tablet — lainnya, desktop — ketiga.

Apple memperkenalkan Size Classes di iOS 8 (2014) bersama dengan aplikasi universal (universal binaries yang berfungsi di iPhone dan iPad). Google memperkenalkan kualifikator smallestWidth (swdp) di Android 3.2 (2011). Kedua mekanisme memecahkan masalah yang sama: memberi pengembang alat untuk membuat UI berbeda untuk layar berbeda tanpa duplikasi kode.

Rekomendasi modern Apple HIG dan Google Material Design sepakat bahwa adaptive layout wajib untuk aplikasi yang mendukung lebih dari satu ukuran layar. Google Play menandai kurangnya adaptasi untuk tablet sebagai kekurangan. App Store tidak memiliki persyaratan formal, tetapi pengguna iPad mengharapkan pengalaman native, bukan aplikasi iPhone yang diregangkan.

Size Classes dan UITraitCollection di iOS

Size Classes — fitur iOS yang mendefinisikan ruang yang tersedia sebagai Compact atau Regular di setiap sumbu. UITraitCollection — sistem iOS untuk mentransmisikan karakteristik lingkungan melalui hierarki view: ukuran, skala layar, force touch capability, gamut warna (light/dark), accessibility settings.

Perangkat / OrientasiHorizontalVertical
iPhone potret (semua model)CompactRegular
iPhone Plus/Pro Max lanskapRegularCompact
iPhone SE / mini lanskapCompactCompact
iPad potretRegularRegular
iPad lanskapRegularRegular
iPad Split View (1/3 layar)CompactRegular

UITraitCollection dibentuk oleh sistem dan ditransmisikan dari UIApplication melalui UIWindow ke setiap UIView. Saat orientasi atau ukuran jendela berubah (Split View), sistem menghasilkan UITraitCollection baru dan memanggil traitCollectionDidChange. Di SwiftUI, perubahan dilacak melalui Environment Values dan secara otomatis menggambar ulang view.

Contoh tata letak adaptif di Swift

Adaptasi melalui UITraitCollection di UIKit diimplementasikan dengan berlangganan perubahan trait collection dan membangun ulang tata letak. Contoh di bawah menunjukkan sebuah controller yang beralih antara stack vertikal untuk iPhone dan tata letak split untuk iPad.

swift
// Kontroler adaptif dengan 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: sidebar + konten
        } else {
            showCompactLayout() // iPhone: bilah tab + 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
    }
}

Metode traitCollectionDidChange dipanggil pada setiap perubahan traits, tetapi kita hanya memeriksa horizontalSizeClass — indikator paling signifikan untuk perubahan tata letak. Di iOS 17+ disarankan menggunakan UIViewController.horizontalSizeClass sebagai computed property untuk pembaruan reaktif tanpa berlangganan perubahan.

Kualifikator Android: sw600dp dan w600dp

Android menyediakan dua kualifikator lebar utama: swdp (smallestWidth) dan wdp (available width). Perbedaannya kritis: sw — lebar minimum layar terlepas dari orientasi, w — lebar tersedia dengan mempertimbangkan orientasi saat ini. sw menjamin bahwa tata letak akan dimuat untuk perangkat yang secara fisik memiliki lebar minimum yang ditentukan. w bereaksi terhadap rotasi — dalam mode lanskap dapat mengaktifkan w600dp, bahkan jika dalam potret lebarnya 360 dp.

KualifikatorKondisiContoh perangkat
layout-sw600dpLebar minimum ≥ 600 dpiPad (768 dp), Pixel C (900 dp)
layout-w600dpLebar saat ini ≥ 600 dpiPad di Split View (600 dp), telepon dalam lanskap
layout-landOrientasi lanskapPerangkat apa pun diputar horizontal
layout-sw720dpLebar minimum ≥ 720 dpiPad Pro (833 dp), Galaxy Tab S9 (800 dp)

Hierarki sumber daya di Android: res/layout/activity_main.xml (telepon), res/layout-sw600dp/activity_main.xml (tablet 7"), res/layout-w600dp-land/activity_main.xml (telepon dalam lanskap). Android memilih kualifikator paling spesifik yang sesuai dengan konfigurasi perangkat saat ini. Jika tidak ada file yang cocok, sumber daya dasar dari res/layout/ digunakan.

Contoh tata letak adaptif di Kotlin

Pengembangan Android modern menggunakan Jetpack WindowManager untuk menentukan ukuran jendela daripada membaca sumber daya secara langsung. Ini sangat penting untuk perangkat lipat, di mana ukuran layar dapat berubah secara dinamis (Galaxy Fold terbuka dari 6,2" menjadi 7,6").

kotlin
// Adaptasi melalui 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("Telepon", 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()
    }
}

Komponen currentWindowAdaptiveInfo() dari pustaka androidx.window menyesuaikan antarmuka dengan perangkat apa pun: telepon, tablet, lipat, ChromeOS. Kelas lebar: COMPACT (0–600 dp), MEDIUM (600–840 dp), EXPANDED (>840 dp). Kelas tinggi: COMPACT (0–480 dp), MEDIUM (480–900 dp), EXPANDED (>900 dp).

Adaptive Layout di SwiftUI

SwiftUI menyediakan alat bawaan untuk tata letak adaptif tanpa penggunaan langsung Size Classes. AnyLayout, ViewThatFits, dan GeometryReader memungkinkan membangun antarmuka yang secara otomatis menyesuaikan dengan ruang yang tersedia.

swift
// Adaptasi SwiftUI melalui AnyLayout dan 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("Favorit", systemImage: "star")
            Label("Terbaru", systemImage: "clock")
            Label("Pengaturan", systemImage: "gear")
        }
        .padding()
    }
}

// ViewThatFits — pemilihan tata letak otomatis
struct SmartLayout: View {
    var body: some View {
        ViewThatFits {
            HStack { // Prioritas 1: horizontal
                CardView()
                CardView()
            }
            VStack { // Jika tidak muat — vertikal
                CardView()
                CardView()
            }
        }
    }
}

ViewThatFits — alat SwiftUI yang kuat yang secara otomatis memilih view anak pertama yang muat di ruang yang tersedia tanpa terpotong. Ini menghilangkan kebutuhan untuk memeriksa Size Classes secara eksplisit untuk perpindahan adaptif sederhana. AnyLayout memungkinkan mengubah tipe tata letak (HStack/VStack) tanpa if-else di dalam body view.

Adaptive Layout di Jetpack Compose

Jetpack Compose menggunakan WindowSizeClass (dari pustaka Material 3 adaptive) dan BoxWithConstraints untuk tata letak adaptif. Berbeda dengan kualifikator XML, Compose menentukan ukuran jendela saat runtime dan menyusun ulang UI secara reaktif saat konfigurasi berubah.

kotlin
// Adaptasi Jetpack Compose melalui BoxWithConstraints
@Composable
fun AdaptiveList(items: List<String>) {
    BoxWithConstraints {
        val width = maxWidth

        if (width >= 600.dp) {
            // Tablet: dua kolom (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 {
            // Telepon: satu kolom dengan navigasi
            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 menyediakan komponen siap pakai: ListDetailScaffold, SupportingPaneScaffold, NavigationSuiteScaffold. Komponen-komponen ini secara otomatis menyesuaikan dengan WindowWidthSizeClass — beralih antara stacked (COMPACT) dan side-by-side (MEDIUM/EXPANDED). Pengembang hanya perlu memilih pola dan memberikan panel konten.

Pertanyaan yang Sering Diajukan

Apa perbedaan antara sw600dp dan w600dp?

sw600dp (smallestWidth) — lebar minimum layar terlepas dari orientasi. Selalu aktif di tablet 7"+. w600dp (available width) — lebar tersedia dengan mempertimbangkan orientasi saat ini. Aktif di telepon dalam lanskap, di mana lebar dapat melebihi 600 dp.

Apa itu UITraitCollection di iOS?

UITraitCollection — objek iOS yang berisi karakteristik lingkungan: size classes (horizontal/vertical), display scale, force touch capability, user interface idiom (iPhone/iPad), color gamut, accessibility settings. Ditransmisikan dari UIApplication melalui hierarki view dan berubah saat orientasi atau ukuran jendela berubah.

Bagaimana cara menyesuaikan aplikasi untuk perangkat lipat?

Gunakan Jetpack WindowManager (Android) dan UIScreen nativeBounds + traitCollection (iOS). Perangkat lipat mengubah Size Class saat dibuka. Arsitektur berdasarkan tata letak kanonis (list-detail, supporting pane) dengan langganan reaktif terhadap perubahan ukuran jendela tanpa memulai ulang Activity direkomendasikan.

Apakah perlu membuat storyboards terpisah untuk iPad?

Tidak. Gunakan satu storyboard dengan variasi Size Classes constraint atau tata letak programatik melalui UIKit. SwiftUI sama sekali tidak memerlukan storyboards. Storyboards terpisah untuk iPad menciptakan duplikasi dan mempersulit pemeliharaan — lebih baik menyesuaikan satu tata letak melalui Size Classes.

Apa itu canonical layouts di Material 3?

Canonical layouts — pola tata letak adaptif siap pakai dari Google: list-detail (daftar + detail), supporting pane (konten + panel tindakan), feed (kartu). Setiap pola mendukung tiga keadaan (compact/medium/expanded) dan diimplementasikan di pustaka Material 3 Adaptive melalui ListDetailScaffold dan SupportingPaneScaffold.

Ringkasan

  • Adaptive Layout — perpindahan diskrit tata letak di titik breakpoint untuk perangkat berbeda
  • Size Classes iOS (Compact/Regular) menentukan tata letak untuk iPhone, iPad, dan Split View
  • UITraitCollection — mekanisme transmisi karakteristik lingkungan melalui hierarki view
  • sw600dp — kualifikator lebar minimum Android untuk tablet 7"+
  • w600dp — kualifikator lebar tersedia yang aktif saat rotasi ke lanskap
  • Jetpack WindowManager menyediakan WindowSizeClass (WindowWidthSizeClass: COMPACT/MEDIUM/EXPANDED)
  • Material 3 Adaptive — komponen siap pakai dengan penyesuaian otomatis (ListDetailScaffold)

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga