Tugas 3 PPB - Membuat Aplikasi "Birthday Greetings"
Tugas 3 - Aplikasi Birthday Greetings Menggunakan Jetpack Compose
Pada tugas ini saya membuat aplikasi Android sederhana bertema birthday greetings menggunakan Jetpack Compose. Aplikasi ini dirancang seperti kartu ucapan ulang tahun digital dengan dua layar utama, yaitu layar pembuka dan layar ucapan. Fokus utama dari project ini bukan hanya pada tampilan, tetapi juga pada bagaimana setiap blok kode bekerja untuk mengatur state, transisi antarlayar, popup, dan komponen visual dekoratif.
1. Informasi Pribadi
| Nama | Dapunta Adyapaksi Ratyanasja |
|---|---|
| NRP | 5025231187 |
| Kelas | Pemrograman Perangkat Bergerak (C) |
| Judul Tugas | Membuat Aplikasi Birthday Greetings Menggunakan Jetpack Compose |
| Bahasa | Kotlin |
| Toolkit UI | Jetpack Compose |
2. Gambaran Umum Aplikasi
Aplikasi ini dibuat dengan alur interaksi sederhana. Saat aplikasi pertama kali dibuka, pengguna akan melihat pesan pembuka yang ditujukan kepada penerima ucapan, dalam hal ini Sam. Setelah tombol Open the Gift ditekan, aplikasi menampilkan popup singkat sebagai efek pembukaan hadiah. Setelah itu, tampilan berpindah ke layar ucapan ulang tahun yang berisi pesan utama dan tombol untuk mengulang kembali.
Nama pengirim dan penerima pada aplikasi ini dibuat statis dan hardcode, yaitu from = "Dapunta"
dan to = "Sam"
3. Fitur dan Fungsionalitas Aplikasi
| Layar pembuka | Menampilkan pesan awal yang mengajak penerima untuk membuka hadiah. |
|---|---|
| Tombol interaktif | Tombol Open the Gift memicu popup dan transisi ke layar berikutnya. |
| Popup hadiah | Muncul sementara sebagai efek bahwa hadiah sedang dibuka. |
| Transisi layar | Perpindahan dari layar pembuka ke layar ucapan dilakukan dengan animasi AnimatedContent. |
| Layar ucapan | Menampilkan teks ucapan ulang tahun dengan nama penerima dan pengirim. |
| Tombol ulang | Tombol See Again mengembalikan aplikasi ke layar awal. |
| Dekorasi visual | Menggunakan gradient background, card, emoji, dan kombinasi warna cerah agar tampilan lebih menarik. |
4. Kode Program Utama
File utama MainActivity.kt yang berisi seluruh logika aplikasi. Pada project ini, seluruh UI ditulis langsung menggunakan Compose tanpa file XML.
package com.example.birthday
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.delay
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
BirthdayApp()
}
}
}
}
@Composable
fun BirthdayApp() {
val from = "Dapunta"
val to = "Sam"
var showGreetingScreen by remember { mutableStateOf(false) }
var showPopup by remember { mutableStateOf(false) }
if (showPopup) {
AlertDialog(
onDismissRequest = { },
confirmButton = {},
title = {
Text(
text = "🎁 Opening your gift...",
fontWeight = FontWeight.Bold
)
},
text = {
Text("A special surprise is on the way for $to ✨")
},
containerColor = Color(0xFFFFF4FB),
shape = RoundedCornerShape(20.dp)
)
LaunchedEffect(Unit) {
delay(1200)
showPopup = false
showGreetingScreen = true
}
}
AnimatedContent(
targetState = showGreetingScreen,
transitionSpec = { fadeIn() togetherWith fadeOut() },
label = "birthday_screen_transition"
) { isGreetingScreen ->
if (isGreetingScreen) {
GreetingScreen(
from = from,
to = to,
onReplay = { showGreetingScreen = false }
)
} else {
IntroScreen(
to = to,
onOpenGift = { showPopup = true }
)
}
}
}
@Composable
fun IntroScreen(
to: String,
onOpenGift: () -> Unit
) {
val bgBrush = Brush.verticalGradient(
colors = listOf(
Color(0xFFFFD6E8),
Color(0xFFFFF1C9),
Color(0xFFD6F4FF)
)
)
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Transparent
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(bgBrush)
.statusBarsPadding()
.padding(20.dp)
) {
DecorativeEmojisTop()
Column(
modifier = Modifier
.fillMaxSize()
.padding(top = 40.dp, bottom = 24.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "🎉 Birthday Surprise 🎉",
fontSize = 28.sp,
fontWeight = FontWeight.ExtraBold,
color = Color(0xFF7A2E5D),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(24.dp))
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(28.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White.copy(alpha = 0.92f)
),
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp)
) {
Column(
modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "🎁",
fontSize = 72.sp
)
Spacer(modifier = Modifier.height(12.dp))
Text(
text = "Hi $to, I have something special for you!\nPlease open the box!",
fontSize = 22.sp,
lineHeight = 30.sp,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF4E3A59),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(24.dp))
Button(
onClick = onOpenGift,
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFFFF5E9C),
contentColor = Color.White
),
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
) {
Text(
text = "Open the Gift",
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
}
}
}
}
DecorativeEmojisBottom(
modifier = Modifier.align(Alignment.BottomCenter)
)
}
}
}
@Composable
fun GreetingScreen(
from: String,
to: String,
onReplay: () -> Unit
) {
val bgBrush = Brush.verticalGradient(
colors = listOf(
Color(0xFF8EC5FC),
Color(0xFFE0C3FC),
Color(0xFFFFDEE9)
)
)
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Transparent
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(bgBrush)
.statusBarsPadding()
.padding(20.dp)
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "🎂✨🎈",
fontSize = 48.sp
)
Spacer(modifier = Modifier.height(16.dp))
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(30.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White.copy(alpha = 0.93f)
),
elevation = CardDefaults.cardElevation(defaultElevation = 10.dp)
) {
Column(
modifier = Modifier.padding(28.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Happy Birthday, $to!",
fontSize = 30.sp,
fontWeight = FontWeight.ExtraBold,
color = Color(0xFF9C2F6B),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(18.dp))
Text(
text = "Wish you all the best. I hope your dreams come true and your days are always filled with happiness, laughter, and love.\n\nFrom the deepest heart,\n$from",
fontSize = 20.sp,
lineHeight = 30.sp,
color = Color(0xFF4C4060),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(24.dp))
Button(
onClick = onReplay,
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF7B61FF),
contentColor = Color.White
),
modifier = Modifier
.fillMaxWidth()
.height(54.dp)
) {
Text(
text = "See Again",
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
}
}
}
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "🎉 🎊 💖 🌟 🎁",
fontSize = 30.sp
)
}
}
}
}
@Composable
fun DecorativeEmojisTop() {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = "🎈", fontSize = 32.sp)
Text(text = "✨", fontSize = 28.sp)
Text(text = "🎉", fontSize = 30.sp)
}
}
@Composable
fun DecorativeEmojisBottom(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.clip(RoundedCornerShape(20.dp))
.background(Color.White.copy(alpha = 0.35f))
.padding(vertical = 10.dp, horizontal = 14.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "🎂", fontSize = 28.sp)
Text(text = "💖", fontSize = 28.sp)
Text(text = "🎁", fontSize = 28.sp)
Text(text = "🎊", fontSize = 28.sp)
Text(text = "🌟", fontSize = 28.sp)
}
}
5. Penjelasan Kode dan Fungsinya
a. Baris package com.example.birthday
Baris package digunakan untuk menandai lokasi file Kotlin di dalam struktur project.
Package membantu pengelompokan file program agar rapi dan memudahkan Android Studio mengenali struktur project.
b. Blok import ...
Bagian import dipakai untuk mengambil class dan fungsi yang dibutuhkan. Pada kode ini,
import digunakan untuk memanggil komponen Compose seperti Text, Button, Card,
AlertDialog, serta fitur animasi seperti AnimatedContent. Selain itu, ada juga import
untuk remember dan mutableStateOf yang berperan penting dalam pengelolaan state.
c. Blok class MainActivity : ComponentActivity()
Ini adalah activity utama yang pertama kali berjalan ketika aplikasi dibuka. Karena aplikasi menggunakan Compose,
activity mewarisi ComponentActivity agar bisa menampilkan antarmuka melalui setContent.
d. Fungsi onCreate()
Fungsi onCreate() adalah titik awal activity. Pada bagian ini, UI utama langsung dimasukkan ke layar
melalui setContent. Di dalamnya juga digunakan MaterialTheme agar tampilan mengikuti gaya Material Design.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
BirthdayApp()
}
}
}
}
e. Fungsi BirthdayApp() sebagai pusat alur aplikasi
Fungsi BirthdayApp() adalah composable utama yang menjadi pusat kontrol aplikasi. Pada blok ini terdapat
data statis pengirim dan penerima, state untuk menentukan apakah layar ucapan sudah ditampilkan, serta state untuk
mengatur popup pembukaan hadiah.
@Composable
fun BirthdayApp() {
val from = "Dapunta"
val to = "Sam"
var showGreetingScreen by remember { mutableStateOf(false) }
var showPopup by remember { mutableStateOf(false) }
}
Dua variabel state di atas sangat penting. Nilai showGreetingScreen menentukan apakah yang ditampilkan
adalah layar awal atau layar ucapan. Nilai showPopup menentukan apakah dialog pembukaan hadiah sedang aktif.
Karena keduanya disimpan sebagai state Compose, setiap perubahan nilainya akan langsung memperbarui tampilan secara otomatis.
f. Data pengirim dan penerima
Nama pengirim dan penerima dibuat statis.
val from = "Dapunta"
val to = "Sam"
Keuntungan pendekatan ini adalah logika aplikasi menjadi lebih sederhana. Nama tidak perlu diambil dari input pengguna, sehingga fokus pengerjaan ada pada flow UI dan transisinya.
g. Blok if (showPopup) untuk menampilkan dialog
Ketika tombol Open the Gift ditekan, state showPopup berubah menjadi true.
Akibatnya, blok if (showPopup) dijalankan dan dialog muncul di layar.
if (showPopup) {
AlertDialog(
onDismissRequest = { },
confirmButton = {},
title = {
Text(
text = "🎁 Opening your gift...",
fontWeight = FontWeight.Bold
)
},
text = {
Text("A special surprise is on the way for $to ✨")
}
)
}
Dialog ini berfungsi sebagai efek transisi sementara, seolah-olah hadiah sedang dibuka sebelum pengguna masuk ke layar utama ucapan.
Karena confirmButton = {}, dialog ini tidak menampilkan tombol aksi tambahan. Jadi dialog hanya berperan sebagai
tampilan sementara, bukan dialog interaktif biasa.
h. Blok LaunchedEffect(Unit) dan delay(1200)
Setelah popup muncul, aplikasi tidak langsung berpindah layar. Di sini digunakan LaunchedEffect untuk menjalankan
proses tertunda selama 1200 milidetik. Setelah jeda selesai, popup ditutup dan layar ucapan ditampilkan.
LaunchedEffect(Unit) {
delay(1200)
showPopup = false
showGreetingScreen = true
}
Secara fungsional, blok ini adalah inti dari efek “membuka hadiah”. Tanpa blok ini, popup tidak akan punya durasi tampil, dan perpindahan layar akan terasa terlalu mendadak.
i. Blok AnimatedContent(...) untuk perpindahan layar
Perpindahan antara layar pembuka dan layar ucapan diatur dengan AnimatedContent. Komponen ini memantau nilai
showGreetingScreen. Jika nilainya false, layar awal yang ditampilkan. Jika nilainya true,
aplikasi menampilkan layar ucapan.
AnimatedContent(
targetState = showGreetingScreen,
transitionSpec = { fadeIn() togetherWith fadeOut() },
label = "birthday_screen_transition"
) { isGreetingScreen ->
if (isGreetingScreen) {
GreetingScreen(
from = from,
to = to,
onReplay = { showGreetingScreen = false }
)
} else {
IntroScreen(
to = to,
onOpenGift = { showPopup = true }
)
}
}
Efek fadeIn() dan fadeOut() membuat perpindahan antarlayar terasa lebih halus.
Secara visual, pengguna tidak merasa seperti masuk ke halaman yang benar-benar terpisah, melainkan seperti membuka lembar ucapan digital.
j. Fungsi IntroScreen()
Fungsi ini bertugas menampilkan layar pertama aplikasi. Di layar ini terdapat judul Birthday Surprise, pesan pembuka, gambar emoji kado, tombol Open the Gift, dan elemen dekoratif di bagian atas serta bawah.
@Composable
fun IntroScreen(
to: String,
onOpenGift: () -> Unit
)
Parameter to digunakan untuk menyisipkan nama penerima ke dalam teks, sedangkan onOpenGift
adalah callback yang dijalankan saat tombol dibuka. Dengan pola seperti ini, UI dan logika bisa dipisahkan dengan rapi.
k. Gradient background pada layar awal
Warna latar layar awal dibuat menggunakan Brush.verticalGradient. Ini membuat tampilan lebih menarik dibanding
satu warna polos biasa.
val bgBrush = Brush.verticalGradient(
colors = listOf(
Color(0xFFFFD6E8),
Color(0xFFFFF1C9),
Color(0xFFD6F4FF)
)
)
Kombinasi warna pink, kuning lembut, dan biru muda dipilih agar memberi kesan ceria, hangat, dan cocok untuk tema ulang tahun.
l. Blok Surface, Box, dan Column
Tiga komponen ini dipakai sebagai kerangka layout utama.
Surfaceberfungsi sebagai wadah dasar layar.Boxdipakai untuk menumpuk elemen, misalnya dekorasi atas, isi utama, dan dekorasi bawah.Columndigunakan untuk menyusun isi secara vertikal dari atas ke bawah.
Dengan kombinasi ini, struktur layout menjadi sederhana namun tetap fleksibel.
m. Penggunaan Card sebagai area isi utama
Isi pesan utama diletakkan dalam Card. Card memberi tampilan seperti kartu ucapan modern dengan sudut membulat,
background putih transparan, dan bayangan halus.
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(28.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White.copy(alpha = 0.92f)
),
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp)
)
Secara fungsional, card membuat konten utama lebih fokus dan mudah dibaca karena terpisah jelas dari background dekoratif.
n. Tombol Open the Gift
Tombol ini adalah pemicu utama flow aplikasi. Saat ditekan, callback onOpenGift akan dijalankan, yang pada akhirnya
mengubah state showPopup menjadi true.
Button(
onClick = onOpenGift,
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFFFF5E9C),
contentColor = Color.White
)
) {
Text(
text = "Open the Gift",
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
}
Jadi, satu klik pada tombol ini memulai tiga hal sekaligus: dialog muncul, waktu tunggu berjalan, lalu layar berubah ke ucapan ulang tahun.
o. Fungsi GreetingScreen()
Fungsi ini menampilkan layar kedua, yaitu layar utama ucapan ulang tahun. Di dalamnya ada judul ucapan, isi pesan, nama pengirim, tombol untuk mengulang, dan dekorasi emoji.
@Composable
fun GreetingScreen(
from: String,
to: String,
onReplay: () -> Unit
)
Parameter from dan to digunakan untuk menampilkan pesan personal. Sedangkan
onReplay digunakan untuk mengembalikan tampilan ke layar awal.
p. Gradient background pada layar ucapan
Layar ucapan juga memakai gradient, tetapi dengan kombinasi warna yang berbeda agar terasa sebagai momen spesial setelah hadiah dibuka.
val bgBrush = Brush.verticalGradient(
colors = listOf(
Color(0xFF8EC5FC),
Color(0xFFE0C3FC),
Color(0xFFFFDEE9)
)
)
Warna biru, ungu muda, dan pink lembut memberi kesan manis dan elegan, sehingga ucapan terasa lebih hangat.
q. Teks ucapan utama
Judul ucapan dibuat dengan ukuran besar, tebal, dan warna yang kontras. Ini penting karena judul adalah pusat perhatian utama layar kedua.
Text(
text = "Happy Birthday, $to!",
fontSize = 30.sp,
fontWeight = FontWeight.ExtraBold,
color = Color(0xFF9C2F6B),
textAlign = TextAlign.Center
)
Nama penerima dimasukkan langsung ke dalam string, sehingga tampilan menjadi lebih personal walaupun datanya tetap hardcode.
r. Isi pesan ucapan
Pesan ucapan ditulis dalam bahasa Inggris sesuai kebutuhan tugas. Pesan ini ditampilkan dengan Text biasa,
tetapi diberi lineHeight agar lebih nyaman dibaca.
Text(
text = "Wish you all the best. I hope your dreams come true and your days are always filled with happiness, laughter, and love.\n\nFrom the deepest heart,\n$from",
fontSize = 20.sp,
lineHeight = 30.sp,
color = Color(0xFF4C4060),
textAlign = TextAlign.Center
)
Bagian ini merupakan inti isi kartu ucapan. Nama pengirim kembali ditampilkan di akhir pesan untuk memberi kesan seperti surat pribadi.
s. Tombol See Again
Tombol ini dipakai untuk mengulang alur aplikasi dari awal. Saat ditekan, callback onReplay akan dijalankan
dan nilai showGreetingScreen diubah kembali menjadi false.
Button(
onClick = onReplay,
shape = RoundedCornerShape(18.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF7B61FF),
contentColor = Color.White
)
) {
Text(
text = "See Again",
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
}
Secara fungsional, tombol ini membuat aplikasi bisa digunakan berulang kali tanpa perlu menutup dan membuka ulang aplikasi.
t. Fungsi DecorativeEmojisTop() dan DecorativeEmojisBottom()
Dua fungsi ini dibuat khusus untuk elemen dekoratif. Keduanya tidak mengandung logika interaksi, tetapi berperan penting dalam mempercantik UI.
@Composable
fun DecorativeEmojisTop() {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = "🎈", fontSize = 32.sp)
Text(text = "✨", fontSize = 28.sp)
Text(text = "🎉", fontSize = 30.sp)
}
}
@Composable
fun DecorativeEmojisBottom(modifier: Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.clip(RoundedCornerShape(20.dp))
.background(Color.White.copy(alpha = 0.35f))
.padding(vertical = 10.dp, horizontal = 14.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "🎂", fontSize = 28.sp)
Text(text = "💖", fontSize = 28.sp)
Text(text = "🎁", fontSize = 28.sp)
Text(text = "🎊", fontSize = 28.sp)
Text(text = "🌟", fontSize = 28.sp)
}
}
Dengan membuat dekorasi sebagai composable terpisah, kode menjadi lebih modular, lebih mudah dibaca, dan lebih mudah dikembangkan lagi nanti.
6. Alur Kerja Aplikasi Secara Keseluruhan
Android menjalankan MainActivity, lalu setContent memanggil BirthdayApp().
Pada kondisi awal, showGreetingScreen = false dan showPopup = false,
sehingga layar yang ditampilkan adalah IntroScreen.
Tombol menjalankan callback onOpenGift yang mengubah showPopup menjadi true.
Karena itu, dialog hadiah ditampilkan di layar.
Saat popup aktif, LaunchedEffect menunggu selama 1200 milidetik. Setelah itu, popup ditutup
dan state showGreetingScreen diubah menjadi true.
Karena target state pada AnimatedContent berubah, Compose mengganti tampilan dari
IntroScreen menjadi GreetingScreen dengan animasi fade.
Jika tombol See Again ditekan, state showGreetingScreen kembali menjadi false.
Akibatnya, layar kembali ke tampilan awal.
7. Kelebihan Implementasi Ini
- Struktur kode relatif ringkas karena menggunakan Jetpack Compose tanpa XML.
- State dikelola dengan sederhana menggunakan
rememberdanmutableStateOf. - Alur aplikasi jelas karena hanya berpusat pada dua state utama.
- Tampilan lebih menarik berkat gradient, card, dan emoji dekoratif.
- Kode modular karena layar dan dekorasi dipisah menjadi beberapa composable.
- Transisi antar tampilan terasa halus dengan
AnimatedContent.
8. Screenshot Aplikasi
9. Penutup
Dari tugas ini saya belajar bahwa Jetpack Compose sangat memudahkan pembuatan aplikasi Android sederhana dengan tampilan yang menarik. Meskipun project ini tidak terlalu kompleks, di dalamnya sudah terdapat konsep penting seperti composable function, state management, callback interaksi, popup, animasi transisi, layout, dan styling. Dengan latihan seperti ini, saya jadi lebih memahami bagaimana menyusun aplikasi Android modern secara deklaratif menggunakan Kotlin dan Jetpack Compose.

Komentar
Posting Komentar