1. Ders: Birleştirilebilir işlevler
Jetpack Compose, oluşturulabilir işlevleri temel alır. Bu işlevler, kullanıcı arayüzünün oluşturulma sürecine (bir öğeyi başlatma, üst öğeye ekleme vb.) odaklanmak yerine nasıl görünmesi gerektiğini açıklayıp veri bağımlılıkları sağlayarak uygulamanızın kullanıcı arayüzünü programatik olarak tanımlamanıza olanak tanır. Oluşturulabilir bir işlev oluşturmak için işlev adına @Composable
ek açıklamasını eklemeniz yeterlidir.
Metin öğesi ekle
Başlamak için Android Studio'nun en son sürümünü indirin ve Yeni Proje'yi seçip Telefon ve Tablet kategorisinin altından Etkinlik Boşalt'ı seçerek bir uygulama oluşturun. Uygulamanızı ComposeEğitim olarak adlandırın ve Son'u tıklayın. Varsayılan şablon, zaten bazı Oluşturma öğelerini içermektedir ancak bu eğitimde bu öğeleri adım adım oluşturacaksınız.
Öncelikle onCreate
yönteminin içine bir metin öğesi ekleyerek "Merhaba dünya!" metnini görüntüleyin. Bunu, bir içerik bloğu tanımlayarak ve
Text
composable işlevini çağırarak yaparsınız. setContent
bloku, etkinlik işlevlerinin çağrıldığı düzeni tanımlar. Oluşturulabilir işlevler, yalnızca diğer birleştirilebilir işlevlerden çağrılabilir.
Jetpack Compose, bu oluşturulabilir işlevleri uygulamanın kullanıcı arayüzü öğelerine dönüştürmek için bir Kotlin derleyici eklentisi kullanır. Örneğin, Oluştur kullanıcı arayüzü kitaplığı tarafından tanımlanan Text
composable işlevi, ekranda bir metin etiketi görüntüler.
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!") } } }

Oluşturulabilir bir işlev tanımlayın
Bir işlevi oluşturulabilir hale getirmek için @Composable
ek açıklamasını ekleyin.
Bunu denemek için, ad ileten bir MessageCard
işlevi tanımlayın ve bu işlevi metin öğesini yapılandırmak için kullanın.
// ... 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!") }

İşlevinizi Android Studio'da önizleme
@Preview
ek açıklaması, uygulamayı oluşturup bir Android cihaz veya emülatöre yüklemek zorunda kalmadan Android Studio'da oluşturulabilir işlevlerinizi önizlemenize olanak tanır. Ek açıklama, parametre almayan bir şekilde oluşturulabilir işlevde kullanılmalıdır. Bu nedenle, MessageCard
işlevini doğrudan önizleyemezsiniz. Bunun yerine, PreviewMessageCard
adlı ikinci bir işlev oluşturun. Bu işlev, MessageCard
öğesini uygun bir parametreyle çağırır. @Preview
ek açıklamasını @Composable
ifadesinden önce ekleyin.
// ... import androidx.compose.ui.tooling.preview.Preview @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } @Preview @Composable fun PreviewMessageCard() { MessageCard("Android") }

Projenizi yeniden oluşturun. Yeni PreviewMessageCard
işlevi herhangi bir yerde çağrılmadığından uygulamanın kendisi değişmez, ancak Android Studio, bölme (tasarım/kod) görünümünü tıklayarak genişletebileceğiniz bir önizleme penceresi ekler. Bu pencerede, @Preview
ek açıklamasıyla işaretlenmiş oluşturulabilir işlevler tarafından oluşturulan kullanıcı arayüzü öğelerinin önizlemesi gösterilir. Önizlemeleri istediğiniz zaman güncellemek için önizleme penceresinin üst kısmındaki yenile düğmesini tıklayın.

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") }


2. Ders: Düzenler
Kullanıcı arayüzü öğeleri hiyerarşiktir ve öğeler diğer öğelerde yer alır. Compose'da, diğer oluşturulabilecek işlevlerden birleştirilebilir işlevleri çağırarak bir kullanıcı arayüzü hiyerarşisi oluşturursunuz.
Birden çok metin ekleme
Şu ana kadar ilk bir oluşturma işlevinizi ve önizlemenizi oluşturdunuz. Jetpack Compose'un diğer özelliklerini keşfetmek için bazı animasyonlarla genişletilebilen mesajların bir listesini içeren basit bir mesajlaşma ekranı oluşturacaksınız.
Yazarın adını ve ileti içeriğini görüntüleyerek mesajı daha zengin hale getirerek başlayın. İlk olarak, oluşturulabilir parametreyi String
yerine bir Message
nesnesini kabul edecek şekilde değiştirmeniz ve MessageCard
kompozisyonunun içine başka bir Text
öğesi eklemeniz gerekir. Önizlemeyi de güncellediğinizden emin olun.
// ... 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!") ) }

Bu kod, içerik görünümü içinde iki metin öğesi oluşturur. Ancak, bunların nasıl düzenleneceği hakkında bilgi vermediğiniz için metin öğeleri birbirinin üzerine çizilir ve metin okunamaz hale gelir.
Sütun Kullanma
// ... import androidx.compose.foundation.layout.Column @Composable fun MessageCard(msg: Message) { Column { Text(text = msg.author) Text(text = msg.body) } }

Resim öğesi ekleme
Gönderenin profil resmini ekleyerek mesaj kartınızı zenginleştirin. Fotoğraf kitaplığınızdan bir resmi içe aktarmak için Resource Manager'ı veya bu resmi kullanın. İyi yapılandırılmış bir tasarıma sahip olacak şekilde ekleyebileceğiniz ve içine
Image
yerleştirilebilecek bir Row
ekleyin.
// ... 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) } } }

Düzeninizi yapılandırın
Mesaj düzeniniz doğru yapıya sahip, ancak öğeleri iyi aralıklı değil ve resim çok büyük. Oluşturulan bir besteyi süslemek veya yapılandırmak için değiştiriciler kullanılır. Oluşturulan öğenin boyutunu, düzenini ve görünümünü değiştirmenize veya bir öğeyi tıklanabilir hale getirmek gibi üst düzey etkileşimler eklemenize olanak tanır. Daha zengin kompozisyonlar oluşturmak için zincir halinde ekleyebilirsiniz. Düzeni iyileştirmek için bunlardan bazılarını kullanacaksınız.
// ... 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) } } }

3. Ders: Materyal Tasarım
Oluşturma, Materyal Tasarım ilkelerini destekleyecek şekilde oluşturulmuştur. Kullanıcı arayüzü öğelerinin çoğunda Materyal Tasarım kullanıma hazırdır. Bu derste, uygulamanızın stilini Materyal Tasarım widget'larıyla belirleyeceksiniz.
Materyal Tasarım'ı kullanma
Mesaj tasarımınız artık bir düzene sahip, ancak henüz düzgün görünmüyor.
Jetpack Compose, Materyal Tasarım 3'ün ve kullanıcı arayüzü öğelerinin kullanıma hazır bir şekilde uygulanmasını sağlar. Materyal Tasarım stilini kullanarak, oluşturulan MessageCard
öğenizin görünümünü iyileştireceksiniz.
Başlamak için MessageCard
işlevini, ComposeTutorialTheme
projenizde oluşturulan Materyal teması ve Surface
ile sarmalayın.
Bu işlemi hem @Preview
hem de setContent
işlevinde yapın. Böylece bestelerinizin, uygulamanızın temasında tanımlandığı gibi stilleri devralabilir, uygulamanız genelinde tutarlılık sağlayabilirsiniz.
Materyal Tasarım üç temel temel üzerine kurulmuştur: Color
, Typography
ve Shape
.
Öğeleri tek tek ekleyeceksiniz.
Not: Boş Yazma Etkinliği şablonu, projeniz için
MaterialTheme
öğesini özelleştirmenize olanak tanıyan varsayılan bir tema oluşturur.
Projenize ComposeTutorial'dan farklı bir ad verdiyseniz özel temanızı ui.theme
alt paketindeki Theme.kt
dosyasında bulabilirsiniz.
// ... 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!") ) } } }

Renk
Sarmalanmış temadaki renklerle stil belirlemek için MaterialTheme.colorScheme
kullanın. Bu değerleri temada rengin gerekli olduğu her yerde kullanabilirsiniz. Bu örnekte dinamik tema renkleri kullanılmaktadır (cihaz tercihleri tarafından tanımlanır).
Bunu değiştirmek için MaterialTheme.kt
dosyasında dynamicColor
değerini false
olarak ayarlayabilirsiniz.
Başlığın stilini belirleyin ve resme kenarlık ekleyin.
// ... 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) } } }

Yazı biçimi
Materyal Tipografi stilleri MaterialTheme
içinde kullanılabilir. Bunları Text
beste dosyalarına eklemeniz yeterlidir.
// ... @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 ) } } }

Şekil
Shape
ile son rötuşları yapabilirsiniz. İlk olarak, ileti gövde metnini
Surface
e-postasının etrafına sarmalayın. Böylece mesaj gövdesinin şeklinin ve yüksekliğinin özelleştirilmesi sağlanır. Daha iyi bir düzen için iletiye de dolgu eklenmiştir.
// ... 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 ) } } } }

Koyu temayı etkinleştir
Özellikle geceleri parlak bir görüntüden kaçınmak veya sadece cihazın pilinden tasarruf etmek için koyu tema (veya gece modu) etkinleştirilebilir. Materyal Tasarım desteği sayesinde Jetpack Compose, varsayılan olarak koyu temayı işleyebilir. Materyal Tasarım renkleri, metinleri ve arka planları kullanıldığında koyu arka plana otomatik olarak uyum sağlar.
Dosyanızda ayrı işlevler olarak birden çok önizleme oluşturabilir veya aynı işleve birden fazla ek açıklama ekleyebilirsiniz.
Yeni bir önizleme ek açıklaması ekleyip gece modunu etkinleştirin.
// ... 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!") ) } } }

Açık ve koyu temalarla ilgili renk seçenekleri, IDE tarafından oluşturulan Theme.kt
dosyasında tanımlanmıştır.
Şimdiye kadar, farklı stillere sahip bir resim ve iki metin görüntüleyen bir mesaj kullanıcı arayüzü öğesi oluşturdunuz. Bu öğe, hem açık hem de koyu temalarda iyi görünüyor!
// ... 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!") ) } } }


4. Ders: Listeler ve animasyonlar
Listeler ve animasyonlar uygulamalarda her yerdedir. Bu derste, Compose'un liste oluşturmayı nasıl kolay hale getirdiğini ve animasyon eklemeyi nasıl eğlenceli hale getirdiğini öğreneceksiniz.
Mesaj listesi oluşturma
Tek mesajlık sohbet biraz yalnız hissettirir. Bu yüzden, konuşmayı birden fazla mesaj içerecek şekilde değiştireceğiz. Birden çok mesaj gösteren bir Conversation
işlevi oluşturmanız gerekir. Bu kullanım alanı için Compose'un
LazyColumn
ve
LazyRow
özelliklerini kullanın. Bu besteler yalnızca ekranda görünen öğeleri oluşturduğundan uzun listelerde çok verimli olacak şekilde tasarlanmıştır.
Bu kod snippet'inde LazyColumn
öğesinin items
alt öğesi olduğunu görebilirsiniz. Parametre olarak bir List
parametresi alır ve lambda'sı, message
adını verdiğimiz (istediğimiz adı verebiliriz) bir parametre alır. Bu parametre, Message
örneğidir.
Kısacası, bu lambda, sağlanan List
öğesinin her bir öğesi için çağrılır. Görüşmenin hızla başlatılması için örnek veri kümesini projenize kopyalayın.
// ... 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) } }

Genişletirken mesajları canlandır
Sohbet daha ilginç hale geliyor. Animasyonlarla oynama zamanı geldi! Hem içerik boyutunu hem de arka plan rengini animasyon ekleyerek daha uzun bir mesajı genişletme özelliği ekleyeceksiniz. Bu yerel kullanıcı arayüzü durumunu depolamak için bir mesajın genişletilip genişletilmediğini takip etmeniz gerekir. Bu durum değişikliğini takip etmek için
remember
ve
mutableStateOf
işlevlerini kullanmanız gerekir.
Oluşturulabilir işlevler, remember
kullanarak yerel durumu bellekte depolayabilir ve mutableStateOf
öğesine iletilen değerde yapılan değişiklikleri izleyebilir. Bu durumu kullanan besteler (ve alt öğeleri), değer güncellendiğinde otomatik olarak yeniden çizilir. Buna yeniden oluşturma adı verilir.
Compose'un remember
ve mutableStateOf
gibi durum API'leri kullanıldığında durum değişiklikleri, kullanıcı arayüzünü otomatik olarak günceller.
Not: Kotlin'in yetki verilmiş mülk söz dizimini (by
anahtar kelimesi) doğru şekilde kullanmak için aşağıdaki içe aktarmaları eklemeniz gerekir. Alt+Enter veya Option+Enter tuşlarını sizin için ekler.
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 ) } } } }
Artık mesajları tıkladığımızda mesaj içeriğinin arka planını isExpanded
göre değiştirebilirsiniz. Oluşturulabilir öğedeki tıklama etkinliklerini işlemek için clickable
değiştiricisini kullanacaksınız. Yalnızca Surface
öğesinin arka plan rengini değiştirmek yerine arka plan rengini animasyon eklemek için MaterialTheme.colorScheme.surface
değerini yavaş yavaş MaterialTheme.colorScheme.primary
(veya tam tersi) şeklinde değiştirirsiniz. Bunun için animateColorAsState
işlevini kullanırsınız. Son olarak, mesaj kapsayıcı boyutunu yumuşak bir şekilde canlandırmak için animateContentSize
değiştiricisini kullanırsınız:
// ... 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 ) } } } }
Sonraki adımlar
Tebrikler, Oluşturma eğiticisini tamamladınız. Materyal Tasarım ilkeleri kullanılarak tasarlanmış koyu tema ve önizlemeler kullanılarak tasarlanan, resim ve metin içeren genişletilebilir ve animasyonlu mesajların bir listesini verimli bir şekilde gösteren basit bir sohbet ekranı oluşturdunuz ve bunların hepsi 100 satırdan kısa kodda yer alıyor.
Şimdiye kadar öğrendikleriniz:
- Birleştirilebilir işlevleri tanımlama
- Oluşturulabilir öğenize farklı öğeler ekleme
- Oluşturulan düzen öğelerini kullanarak kullanıcı arayüzü bileşeninizi yapılandırma
- Değiştirici kullanarak kompozisyonları genişletme
- Verimli bir liste oluşturma
- Durumu takip etme ve değiştirme
- Oluşturulabilir bir dosyaya kullanıcı etkileşimi ekleme
- İletileri genişletirken canlandırma
Bu adımlardan bazılarını daha ayrıntılı şekilde incelemek isterseniz aşağıdaki kaynaklara göz atabilirsiniz.