Belajar Jetpack Compose - Handling Input & Events
Episode 7 of 23

Belajar Jetpack Compose - Handling Input & Events

Episode ini menguasai interaksi pengguna: TextField, Button, Checkbox, dan Switch, deteksi gesture dengan pointer input, manajemen fokus dan keyboard, validasi input, serta Snackbar, dialog, dan bottom sheet.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Aplikasi tanpa interaksi hanyalah poster digital. Episode 7 membawa kalian dari statis ke interaktif: menangkap input pengguna, mendeteksi gesture, mengelola keyboard dan fokus, serta memberi umpan balik lewat Snackbar, dialog, dan bottom sheet.

Pola yang dipakai di sini konsisten dengan episode 5: state naik, event turun. Setiap kontrol menerima nilai dan callback, dan logika tinggal di hoisted state atau ViewModel.

Episode 7 ini meliputi kontrol input, gesture dan pointer input, fokus dan keyboard, validasi, serta komponen umpan balik.

Kontrol Input: TextField, Button, Checkbox, Switch

Keluarga TextField

OutlinedTextField dan TextField adalah input teks Material 3. Keduanya menerima value dan onValueChange — pola state hoisting yang sudah kalian kenal:

KotlinTextField dengan keyboard options
var email by rememberSaveable { mutableStateOf("") }
 
OutlinedTextField(
    value = email,
    onValueChange = { email = it },
    label = { Text("Email") },
    singleLine = true,
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Email,
        imeAction = ImeAction.Done
    ),
    keyboardActions = KeyboardActions(onDone = { verifikasi() })
)

KeyboardOptions mengatur tipe keyboard (KeyboardType.Email) dan aksi IME (ImeAction.Done), sementara KeyboardActions menangkap saat tombol Done ditekan — pola yang membuat form terasa responsif.

Checkbox dan Switch

Untuk pilihan biner, Checkbox dan Switch memakai state Boolean:

KotlinCheckbox dan Switch
var setuju by remember { mutableStateOf(false) }
var notifikasi by remember { mutableStateOf(true) }
 
Row(verticalAlignment = Alignment.CenterVertically) {
    Checkbox(checked = setuju, onCheckedChange = { setuju = it })
    Text("Setuju dengan syarat")
}
 
Row(verticalAlignment = Alignment.CenterVertically) {
    Switch(checked = notifikasi, onCheckedChange = { notifikasi = it })
    Text("Aktifkan notifikasi")
}

Gesture dan Pointer Input

clickable dan Modifier Pointer

Kebanyakan interaksi cukup dengan modifier clickable, toggleable, atau selectable. Untuk gesture yang lebih kaya, gunakan pointerInput dengan detector:

KotlinDeteksi tap dan long press
Modifier
    .pointerInput(Unit) {
        detectTapGestures(
            onTap = { onTampilkanToast() },
            onLongPress = { onBukaMenu() }
        )
    }
    .padding(16.dp)

detectTapGestures membedakan onTap dan onLongPress. Untuk drag dan pinch, Compose menyediakan detectDragGestures dan detectTransformGestures — dasar untuk komponen seperti carousel yang bisa digeser. Saat menguji tanpa menyentuh layar, adb shell input tap 540 1200 mengirim tap di koordinat tertentu lewat terminal.

Fokus, Keyboard, dan Validasi

Mengelola Fokus

Fokus berpindah saat pengguna menekan tombol IME. FocusRequester memberi kontrol programatik:

KotlinFocusRequester
val passwordFocus = FocusRequester()
OutlinedTextField(
    value = password,
    onValueChange = { password = it },
    modifier = Modifier.focusRequester(passwordFocus)
)
 
LaunchedEffect(Unit) { passwordFocus.requestFocus() }

Modifier.focusRequester(passwordFocus) mendaftarkan requester, dan passwordFocus.requestFocus() memindahkan fokus saat komposisi dimulai — berguna untuk menampilkan keyboard langsung saat layar form dibuka.

Validasi Input

Validasi menghasilkan pesan error yang ditampilkan lewat isError dan supportingText:

KotlinValidasi sederhana
val emailValid = email.contains("@")
OutlinedTextField(
    value = email,
    onValueChange = { email = it },
    isError = !emailValid && email.isNotEmpty(),
    supportingText = {
        if (!emailValid && email.isNotEmpty()) {
            Text("Format email tidak valid")
        }
    }
)

isError menandai field merah, dan supportingText menampilkan pesan. Untuk form kompleks, buat state validasi terpisah agar logika bisa diuji tanpa UI — pola yang akan kita pakai lagi di episode 14.

Snackbar, Dialog, dan Bottom Sheet

Snackbar untuk Umpan Balik

SnackbarHost dan SnackbarHostState menampilkan pesan singkat di bawah layar:

KotlinSnackbar
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
 
Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) }
) { padding ->
    Button(
        onClick = {
            scope.launch {
                snackbarHostState.showSnackbar("Berhasil disimpan")
            }
        },
        modifier = Modifier.padding(padding)
    ) { Text("Simpan") }
}

snackbarHostState.showSnackbar(...) menampilkan pesan; panggilan bersifat suspend, jadi dijalankan dalam rememberCoroutineScope — konsep coroutine di Compose yang akan dibedah di episode 10.

Dialog dan Bottom Sheet

Untuk konfirmasi, AlertDialog; untuk aksi kontekstual, ModalBottomSheet:

KotlinAlertDialog
var tampilkanDialog by remember { mutableStateOf(false) }
 
if (tampilkanDialog) {
    AlertDialog(
        onDismissRequest = { tampilkanDialog = false },
        title = { Text("Hapus item?") },
        text = { Text("Tindakan ini tidak bisa dibatalkan.") },
        confirmButton = {
            Button(onClick = { tampilkanDialog = false }) { Text("Hapus") }
        },
        dismissButton = {
            TextButton(onClick = { tampilkanDialog = false }) { Text("Batal") }
        }
    )
}

AlertDialog muncul hanya saat tampilkanDialog bernilai true. Pola if (state) { Komponen } ini adalah idiom umum Compose untuk overlay — akan muncul lagi saat membahas animasi di episode 12.

Penutup

Episode 7 melengkapi kalian untuk berinteraksi: TextField dengan keyboard options dan validasi, Checkbox dan Switch untuk pilihan biner, gesture dengan pointerInput, kontrol fokus dengan FocusRequester, serta umpan balik lewat Snackbar, AlertDialog, dan ModalBottomSheet.

Inti yang harus dibawa pulang:

  • Semua kontrol mengikuti kontrak nilai dan callback.
  • KeyboardOptions dan ImeAction mengatur perilaku keyboard.
  • FocusRequester memberi kontrol fokus programatik.
  • isError dan supportingText menampilkan validasi langsung di field.
  • SnackbarHostState bekerja dengan coroutine scope.
  • Overlay seperti dialog dikontrol dengan state Boolean.

Di episode 8 selanjutnya kita akan membahas navigation dan app architecture — Navigation Compose dan nav graph, passing arguments, deep links, arsitektur Single Activity, dan pola routing modular.

Belajar Jetpack Compose - Handling Input & Events | Belajar Jetpack Compose