Pelajaran 1: Fungsi composable
        Jetpack Compose dibuat berdasarkan fungsi composable. Fungsi ini memungkinkan Anda menentukan
        UI aplikasi Anda secara terprogram dengan menjelaskan tampilan dan penyediaan dependensi data,
        bukan berfokus pada proses konstruksi UI (memulai elemen,
        melampirkannya ke induk, dll.). Untuk membuat fungsi composable, cukup tambahkan
        anotasi @Composable ke nama fungsi.
      
Menambahkan elemen teks
Untuk memulai, unduh versi terbaru Android Studio, lalu buat aplikasi dengan memilih New Project, dan di bagian Kategori Ponsel dan Tablet, pilih Aktivitas Kosong. Beri nama aplikasi ComposeTutorial, lalu klik Finish. Template default sudah berisi beberapa elemen Compose, tetapi dalam tutorial ini Anda akan mem-build elemen langkah demi langkah.
    Pertama, tampilkan teks “Halo dunia!” dengan menambahkan elemen teks di dalam
    metode onCreate. Anda dapat melakukannya dengan menentukan blok
    konten, dan memanggil
    fungsi composable Text. Blok
    setContent menentukan tata letak aktivitas tempat
    fungsi composable dipanggil. Fungsi composable hanya dapat dipanggil dari fungsi
composable lain.
  
    Jetpack Compose menggunakan plugin compiler Kotlin untuk mengubah fungsi composable ini
    menjadi elemen UI aplikasi. Misalnya, fungsi composable Text yang
    ditetapkan oleh library Compose UI akan menampilkan label teks di layar.
  
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Text class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Text("Hello world!") } } }
 
Menentukan fungsi composable
    Untuk membuat fungsi yang dapat dikomposisi, tambahkan anotasi @Composable.
    Untuk mencoba ini, tentukan fungsi MessageCard yang
    mendapatkan nama dan menggunakan nama tersebut untuk mengonfigurasi elemen teks.
  
// ... import androidx.compose.runtime.Composable class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MessageCard("Android") } } } @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") }
 
Melihat pratinjau fungsi di Android Studio
    Anotasi @Preview memungkinkan Anda melihat pratinjau fungsi composable dalam Android
    Studio tanpa harus mem-build dan menginstal aplikasi ke perangkat Android atau emulator. Anotasi
    ini harus digunakan pada fungsi composable yang tidak menggunakan parameter. Karena
    alasan ini, Anda tidak dapat melihat pratinjau fungsi MessageCard
    secara langsung. Sebagai gantinya, buat fungsi kedua bernama
    PreviewMessageCard, yang memanggil
    MessageCard dengan parameter yang sesuai. Tambahkan
    anotasi @Preview sebelum
    @Composable.
  
// ... import androidx.compose.ui.tooling.preview.Preview @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } @Preview @Composable fun PreviewMessageCard() { MessageCard("Android") }
 
    Membuat ulang project Anda. Aplikasi itu sendiri tidak berubah, karena fungsi
    PreviewMessageCard baru tidak dipanggil di mana pun,
    tetapi Android Studio menambahkan jendela pratinjau yang dapat Anda luaskan dengan mengklik tampilan
    (desain/kode) terpisah. Jendela ini menampilkan pratinjau elemen UI yang dibuat oleh fungsi
    composable yang ditandai dengan anotasi @Preview. Untuk memperbarui
    pratinjau kapan pun, klik tombol muat ulang di bagian atas jendela pratinjau.
  
 
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Text class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Text("Hello world!") } } }
 
// ... import androidx.compose.runtime.Composable class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MessageCard("Android") } } } @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") }
 
// ... import androidx.compose.ui.tooling.preview.Preview @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } @Preview @Composable fun PreviewMessageCard() { MessageCard("Android") }
 
 
Tutorial 2: Tata letak
Elemen UI bersifat hierarkis, dengan elemen satu berada di dalam elemen lainnya. Di Compose, Anda mem-build hierarki UI dengan memanggil fungsi composable dari fungsi composable lainnya.
Menambahkan beberapa teks
Sejauh ini, Anda telah mem-build fungsi composable dan pratinjau pertama. Untuk menemukan kemampuan Jetpack Compose lainnya, Anda akan mem-build layar pesan sederhana yang berisi daftar pesan yang dapat diperluas dengan beberapa animasi.
    Mulailah dengan melengkapi composable pesan, dengan menampilkan nama penulis dan
    konten pesannya. Anda harus mengubah parameter composable terlebih dahulu untuk menerima objek
    Message sebagai ganti
    String, dan menambahkan composable
    Text lain di dalam composable
    MessageCard. Pastikan Anda juga memperbarui
    pratinjau.
  
// ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MessageCard(Message("Android", "Jetpack Compose")) } } } data class Message(val author: String, val body: String) @Composable fun MessageCard(msg: Message) { Text(text = msg.author) Text(text = msg.body) } @Preview @Composable fun PreviewMessageCard() { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) }
 
Kode ini membuat dua elemen teks di dalam tampilan konten. Namun, karena informasi tentang cara mengaturnya belum disediakan, elemen teks tersebut digambar di atas satu sama lain, sehingga membuat teks tidak dapat dibaca.
Menggunakan Kolom
// ... import androidx.compose.foundation.layout.Column @Composable fun MessageCard(msg: Message) { Column { Text(text = msg.author) Text(text = msg.body) } }
 
Menambahkan elemen gambar
    Lengkapi kartu pesan Anda dengan menambahkan foto profil pengirim. Gunakan
    Resource Manager
    untuk mengimpor gambar dari galeri foto Anda atau gunakan yang ini. Tambahkan
    composable Row agar memiliki desain yang terstruktur dengan baik dan
    composable 
    Image di dalamnya.
  
// ... import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Row import androidx.compose.ui.res.painterResource @Composable fun MessageCard(msg: Message) { Row { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", ) Column { Text(text = msg.author) Text(text = msg.body) } } }
 
Mengonfigurasi tata letak Anda
Tata letak pesan Anda memiliki struktur yang tepat, tetapi elemennya tidak diberi spasi dengan baik dan gambarnya terlalu besar. Untuk mendekorasi atau mengonfigurasi composable, Compose menggunakan pengubah. Modifier memungkinkan Anda mengubah ukuran, tata letak, tampilan, atau interaksi tingkat tinggi composable, seperti membuat elemen menjadi dapat diklik. Anda dapat merangkainya untuk membuat composable yang lebih lengkap. Anda akan menggunakan beberapa di antaranya untuk membuat tata letak lebih baik.
// ... import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp @Composable fun MessageCard(msg: Message) { // Add padding around our message Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", modifier = Modifier // Set image size to 40 dp .size(40.dp) // Clip image to be shaped as a circle .clip(CircleShape) ) // Add a horizontal space between the image and the column Spacer(modifier = Modifier.width(8.dp)) Column { Text(text = msg.author) // Add a vertical space between the author and message texts Spacer(modifier = Modifier.height(4.dp)) Text(text = msg.body) } } }
 
// ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MessageCard(Message("Android", "Jetpack Compose")) } } } data class Message(val author: String, val body: String) @Composable fun MessageCard(msg: Message) { Text(text = msg.author) Text(text = msg.body) } @Preview @Composable fun PreviewMessageCard() { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) }
 
 
// ... import androidx.compose.foundation.layout.Column @Composable fun MessageCard(msg: Message) { Column { Text(text = msg.author) Text(text = msg.body) } }
 
// ... import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Row import androidx.compose.ui.res.painterResource @Composable fun MessageCard(msg: Message) { Row { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", ) Column { Text(text = msg.author) Text(text = msg.body) } } }
 
// ... import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp @Composable fun MessageCard(msg: Message) { // Add padding around our message Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = "Contact profile picture", modifier = Modifier // Set image size to 40 dp .size(40.dp) // Clip image to be shaped as a circle .clip(CircleShape) ) // Add a horizontal space between the image and the column Spacer(modifier = Modifier.width(8.dp)) Column { Text(text = msg.author) // Add a vertical space between the author and message texts Spacer(modifier = Modifier.height(4.dp)) Text(text = msg.body) } } }
 
Pelajaran 3: Desain Material
Compose dibuat untuk mendukung prinsip Desain Material. Banyak elemen UI-nya mengimplementasikan Desain Material secara unik. Dalam pelajaran ini, Anda akan menyesuaikan aplikasi dengan widget Desain Material.
Menggunakan Desain Material
Desain pesan Anda sekarang memiliki tata letak, tetapi belum terlihat bagus.
    Jetpack Compose menyediakan implementasi Desain Material 3 dan elemen UI-nya
    sejak awal. Anda akan meningkatkan tampilan composable MessageCard
    menggunakan gaya Desain Material.
  
    Untuk memulai, gabungkan fungsi MessageCard dengan
    tema Material yang dibuat di project Anda, ComposeTutorialTheme, 
    serta Surface.
    Lakukan keduanya di @Preview dan dalam
    fungsi setContent. Dengan melakukannya, composable dapat
    mewarisi gaya seperti yang ditentukan dalam tema aplikasi untuk memastikan konsistensi di seluruh aplikasi.
  
    Desain Material di-build berdasarkan tiga pilar: Color,
    Typography, dan Shape.
    Anda akan menambahkannya satu per satu.
  
    Catatan: Template Empty Compose Activity menghasilkan tema default untuk project Anda,
    yang memungkinkan Anda menyesuaikan 
    MaterialTheme.
    Jika Anda memberi project nama yang berbeda dengan
    ComposeTutorial, Anda dapat menemukan tema kustom di
    file Theme.kt dalam
    sub-paket ui.theme.
  
// ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ComposeTutorialTheme { Surface(modifier = Modifier.fillMaxSize()) { MessageCard(Message("Android", "Jetpack Compose")) } } } } } @Preview @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!") ) } } }
 
Warna
    Gunakan MaterialTheme.colorScheme untuk memberi gaya dengan warna dari
    tema gabungan. Anda dapat menggunakan nilai-nilai ini dari tema di mana pun warna diperlukan. Contoh ini menggunakan warna tema dinamis (yang ditentukan oleh preferensi perangkat). 
    Anda dapat menetapkan dynamicColor ke false dalam file MaterialTheme.kt untuk mengubahnya. 
  
Beri gaya pada judul dan tambahkan bingkai ke gambar.
// ... import androidx.compose.foundation.border import androidx.compose.material3.MaterialTheme @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary ) Spacer(modifier = Modifier.height(4.dp)) Text(text = msg.body) } } }
 
Tipografi
    Gaya Tipografi Material tersedia dalam MaterialTheme,
    cukup tambahkan ke composable Text.
  
// ... @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Text( text = msg.body, style = MaterialTheme.typography.bodyMedium ) } } }
 
Bentuk
    Dengan Shape, Anda dapat menambahkan sentuhan akhir. Pertama, gabungkan
    teks isi pesan di sekitar
    composable 
    Surface. Dengan melakukannya, Anda dapat menyesuaikan
    bentuk dan ketinggian isi pesan. Padding juga ditambahkan ke pesan untuk tata letak yang lebih baik.
  
// ... import androidx.compose.material3.Surface @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), style = MaterialTheme.typography.bodyMedium ) } } } }
 
Mengaktifkan tema gelap
Tema gelap (atau mode malam) dapat diaktifkan untuk menghindari tampilan terang, khususnya pada malam hari, atau hanya untuk menghemat baterai perangkat. Berkat dukungan Desain Material, Jetpack Compose dapat menangani tema gelap secara default. Setelah menggunakan warna Desain Material, teks dan latar belakang akan otomatis menyesuaikan dengan latar belakang gelap.
Anda dapat membuat beberapa pratinjau dalam file sebagai fungsi terpisah, atau menambahkan beberapa anotasi ke fungsi yang sama.
Menambahkan anotasi pratinjau baru dan mengaktifkan mode malam.
// ... import android.content.res.Configuration @Preview(name = "Light Mode") @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, name = "Dark Mode" ) @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) } } }
 
    Pilihan warna untuk tema terang dan gelap ditentukan dalam file Theme.kt
    yang dihasilkan IDE.
  
Sejauh ini, Anda telah membuat elemen UI pesan yang menampilkan gambar dan dua teks dengan gaya berbeda, serta terlihat bagus dalam tema terang dan gelap.
// ... import android.content.res.Configuration @Preview(name = "Light Mode") @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, name = "Dark Mode" ) @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) } } }
 
// ... class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ComposeTutorialTheme { Surface(modifier = Modifier.fillMaxSize()) { MessageCard(Message("Android", "Jetpack Compose")) } } } } } @Preview @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Take a look at Jetpack Compose, it's great!") ) } } }
 
// ... import androidx.compose.foundation.border import androidx.compose.material3.MaterialTheme @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary ) Spacer(modifier = Modifier.height(4.dp)) Text(text = msg.body) } } }
 
// ... @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Text( text = msg.body, style = MaterialTheme.typography.bodyMedium ) } } }
 
// ... import androidx.compose.material3.Surface @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface(shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), style = MaterialTheme.typography.bodyMedium ) } } } }
 
// ... import android.content.res.Configuration @Preview(name = "Light Mode") @Preview( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, name = "Dark Mode" ) @Composable fun PreviewMessageCard() { ComposeTutorialTheme { Surface { MessageCard( msg = Message("Lexi", "Hey, take a look at Jetpack Compose, it's great!") ) } } }
 
 
  Modul 4: Daftar dan animasi
Daftar dan animasi ada di mana saja dalam aplikasi. Dalam modul ini, Anda akan mempelajari bagaimana Compose memudahkan pembuatan daftar dan menyenangkan untuk menambahkan animasi.
Membuat daftar pesan
    Chat dengan satu pesan terasa agak sepi, jadi kita akan mengubah percakapan menjadi memiliki lebih dari
    satu pesan. Anda harus membuat fungsi Conversation
    yang akan menampilkan beberapa pesan. Untuk kasus penggunaan ini, gunakan
    
    LazyColumn dan
    
    LazyRow Compose. Composable ini hanya merender elemen
    yang terlihat di layar, sehingga composable tersebut didesain agar menjadi sangat efisien untuk daftar yang panjang.
  
    Dalam cuplikan kode ini, Anda dapat melihat bahwa LazyColumn memiliki
    turunan items. Perlu List
    sebagai parameter dan lambda-nya
    menerima parameter yang telah kita beri nama message (kita dapat
    menamainya sesuai keinginan) yang merupakan instance Message.
    Singkatnya, lambda ini dipanggil untuk setiap item dari
    List yang disediakan. Salin
    sampel set data
    ke dalam project Anda untuk membantu mem-bootstrap percakapan dengan cepat.
  
// ... import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @Composable fun Conversation(messages: List<Message>) { LazyColumn { items(messages) { message -> MessageCard(message) } } } @Preview @Composable fun PreviewConversation() { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } }
 
Menganimasikan pesan saat meluaskan
    Percakapan menjadi lebih menarik. Saatnya berkreasi dengan animasi! Anda akan menambahkan
    kemampuan untuk meluaskan pesan agar menampilkan pesan yang lebih panjang, yang menganimasikan ukuran konten dan
    warna latar belakang. Untuk menyimpan status UI lokal ini, Anda perlu memantau apakah pesan telah
    diluaskan atau tidak. Untuk memantau perubahan status ini, Anda harus menggunakan fungsi
    remember dan
    mutableStateOf.
  
    Fungsi composable dapat menyimpan status lokal dalam memori menggunakan
    remember, dan memantau perubahan pada nilai yang diteruskan ke
    mutableStateOf. Composable (dan turunannya) yang menggunakan
    status ini akan digambar ulang secara otomatis saat nilai diperbarui. Ini disebut
    rekomposisi.
  
    Dengan menggunakan API status Compose seperti remember dan
    mutableStateOf, perubahan apa pun pada status akan otomatis memperbarui UI.
  
    Catatan: Anda harus menambahkan impor berikut untuk menggunakan metode
    sintaksis properti yang didelegasikan (kata kunci by). Alt+Enter atau Option+Enter akan menambahkannya
     keamanan untuk Anda.
    
      import androidx.compose.runtime.getValue
      import androidx.compose.runtime.setValue
    
  
// ... import androidx.compose.foundation.clickable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } } } } @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) // We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, ) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium ) } } } }
    Sekarang Anda dapat mengubah latar belakang konten pesan berdasarkan
    isExpanded saat kita mengklik pesan. Anda akan menggunakan
    pengubah clickable untuk menangani peristiwa klik pada
    composable. Daripada hanya mengganti warna latar belakang
    Surface, Anda akan menganimasikan warna latar belakang dengan
    mengubah nilainya secara bertahap dari
    MaterialTheme.colorScheme.surface ke
    MaterialTheme.colorScheme.primary, dan sebaliknya. Untuk melakukannya,
    Anda akan menggunakan fungsi animateColorAsState. Terakhir, Anda
    akan menggunakan pengubah animateContentSize untuk menganimasikan
    ukuran penampung pesan dengan lancar:
  
// ... import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateContentSize @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) // We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } // surfaceColor will be updated gradually from one color to the other val surfaceColor by animateColorAsState( if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface, ) // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, // surfaceColor color will be changing gradually from primary to surface color = surfaceColor, // animateContentSize will change the Surface size gradually modifier = Modifier.animateContentSize().padding(1.dp) ) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium ) } } } }
// ... import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @Composable fun Conversation(messages: List<Message>) { LazyColumn { items(messages) { message -> MessageCard(message) } } } @Preview @Composable fun PreviewConversation() { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } }
 
// ... import androidx.compose.foundation.clickable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ComposeTutorialTheme { Conversation(SampleData.conversationSample) } } } } @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) // We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, ) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium ) } } } }
// ... import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateContentSize @Composable fun MessageCard(msg: Message) { Row(modifier = Modifier.padding(all = 8.dp)) { Image( painter = painterResource(R.drawable.profile_picture), contentDescription = null, modifier = Modifier .size(40.dp) .clip(CircleShape) .border(1.5.dp, MaterialTheme.colorScheme.secondary, CircleShape) ) Spacer(modifier = Modifier.width(8.dp)) // We keep track if the message is expanded or not in this // variable var isExpanded by remember { mutableStateOf(false) } // surfaceColor will be updated gradually from one color to the other val surfaceColor by animateColorAsState( if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface, ) // We toggle the isExpanded variable when we click on this Column Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) { Text( text = msg.author, color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.titleSmall ) Spacer(modifier = Modifier.height(4.dp)) Surface( shape = MaterialTheme.shapes.medium, shadowElevation = 1.dp, // surfaceColor color will be changing gradually from primary to surface color = surfaceColor, // animateContentSize will change the Surface size gradually modifier = Modifier.animateContentSize().padding(1.dp) ) { Text( text = msg.body, modifier = Modifier.padding(all = 4.dp), // If the message is expanded, we display all its content // otherwise we only display the first line maxLines = if (isExpanded) Int.MAX_VALUE else 1, style = MaterialTheme.typography.bodyMedium ) } } } }
Langkah berikutnya
Selamat, Anda telah menyelesaikan tutorial Compose! Anda telah membuat layar chat sederhana yang secara efisien menampilkan daftar pesan yang dapat diperluas & animasi yang berisi gambar dan teks, yang didesain menggunakan prinsip Desain Material dengan menyertakan tema gelap dan pratinjau—semuanya kurang dari 100 baris kode!
Berikut yang telah Anda pelajari sejauh ini:
- Menentukan fungsi composable
- Menambahkan berbagai elemen di composable Anda
- Membuat struktur komponen UI menggunakan composable tata letak
- Memperluas composable dengan menggunakan pengubah
- Membuat daftar yang efisien
- Melacak status dan mengubahnya
- Menambahkan interaksi pengguna pada composable
- Menganimasikan pesan saat memperluasnya
Jika Anda ingin menggali lebih dalam beberapa langkah ini, jelajahi referensi di bawah.
 
   
        