1. Ders: Oluşturulabilir işlevler
Jetpack Compose, composable işlevler temel alınarak geliştirilmiştir. Bu işlevler, kullanıcı arayüzünün oluşturma sürecine (bir öğeyi başlatma, üst öğeye ekleme vb.) odaklanmak yerine nasıl görünmesi gerektiğini açıklayarak ve veri bağımlılıklarını sağlayarak uygulamanızın kullanıcı arayüzünü programatik olarak tanımlamanıza olanak tanır. composable işlev oluşturmak için işlev adına @Composable
ek açıklamasını eklemeniz yeterlidir.
Metin öğesi ekleme
Başlamak için Android Studio'nun en son sürümünü indirin ve Yeni Proje'yi seçerek bir uygulama oluşturun, ardından Telefon ve Tablet kategorisinin altında Etkinlik Boşalt'ı seçin. Uygulamanıza ComposeTutorial adını verin ve Finish'i (Son) tıklayın. Varsayılan şablon zaten bazı Compose öğeleri içerir 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
bloğu, etkinliğin composable işlevlerinin çağrıldığı düzenini tanımlar. Oluşturulabilir işlevler yalnızca diğer composable işlevlerden çağrılabilir.
Jetpack Compose bu composable işlevleri uygulamanın kullanıcı arayüzü öğelerine dönüştürmek için bir Kotlin derleyici eklentisi kullanır. Örneğin, Compose 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!") } } }
Bestelenebilir bir işlev tanımlayın
Bir işlevi composable hale getirmek için @Composable
ek açıklamasını ekleyin.
Bunu denemek için, ad iletilen bir MessageCard
işlevi tanımlayın ve bunu 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!") }
Android Studio'da işlevinizi önizleme
@Preview
ek açıklaması, uygulamayı geliştirip bir Android cihaz veya emülatöre yüklemek zorunda kalmadan composable işlevlerinizi Android Studio'da önizlemenize olanak tanır. Ek açıklama, parametre almayan bir composable işlevde kullanılmalıdır. Bu nedenle, MessageCard
işlevini doğrudan önizleyemezsiniz. Bunun yerine, uygun bir parametreyle MessageCard
çağrısı yapan PreviewMessageCard
adlı ikinci bir işlev oluşturun. @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ığı için 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ş composable işlevler tarafından oluşturulan kullanıcı arayüzü öğelerinin önizlemesi gösterilmektedir. Ö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, öğeler diğer öğelerde yer alır. Compose'da diğer composable işlevlerden composable işlevleri çağırarak bir kullanıcı arayüzü hiyerarşisi oluşturursunuz.
Birden çok metin ekleme
Şu ana kadar ilk composable işlevini oluşturup ö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 kapsamlı hale getirerek başlayın. Öncelikle composable parametresini String
yerine bir Message
nesnesini kabul edecek şekilde değiştirmeniz ve MessageCard
composable içine başka bir Text
composable 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 sağlamadığınız 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 olmak için Row
composable ve içinde bir
Image
composable'ı 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 doğru şekilde yerleştirilmemiş ve resim çok büyük. Compose'da bir composable'ı süslemek veya yapılandırmak için değiştiriciler kullanılır. Bunlar, composable'ın 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 composable'lar oluşturmak için bunları zincir şeklinde kullanabilirsiniz. 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ğu, kullanıma hazır Materyal Tasarım'ı kullanır. Bu derste, Materyal Tasarım widget'larıyla uygulamanızın stilini belirleyeceksiniz.
Materyal Tasarım'ı kullanma
Mesaj tasarımınız artık bir düzene sahip, ancak henüz iyi görünmüyor.
Jetpack Compose, Materyal Tasarım 3'ün ve kullanıcı arayüzü öğelerinin kullanıma hazır bir uygulamasını sunar. Materyal Tasarım stilini kullanarak MessageCard
composable'ın 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 composable'larınız, uygulamanızın temasında tanımlanan stilleri devralarak uygulamanız genelinde tutarlılık sağlayabilir.
Materyal Tasarım üç temel dayanağın üzerine inşa edilmiştir: Color
, Typography
ve Shape
.
Bunları tek tek ekleyeceksiniz.
Not: Boş Oluşturma 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 oluşturmak 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
ile kullanılabilir. Bu stilleri Text
composable'ları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, mesaj gövdesi metnini bir
Surface
composable'ının etrafına sarmalayın. Bunun yapılması, ileti gövdesinin şeklinin ve yüksekliğinin özelleştirilmesine olanak tanır. Daha iyi bir düzen için mesaja dolgu da eklenir.
// ... 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
Koyu tema (veya gece modu), özellikle geceleri parlak bir ekranın görüntülenmemesini sağlamak veya yalnızca cihazın pilinden tasarruf etmek için etkinleştirilebilir. Materyal Tasarım desteği sayesinde Jetpack Compose varsayılan olarak koyu temayı işleyebilir. Materyal Tasarım renkleri, metinler ve arka planlar kullanıldıklarında koyu arka plana otomatik olarak uyum sağlanır.
Dosyanızda ayrı işlevler olarak birden çok önizleme oluşturabilir veya aynı işleve birden çok ek açıklama ekleyebilirsiniz.
Yeni bir önizleme ek açıklaması ekleyin ve 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ı stillerde bir resim ve iki metin gösteren 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 uygulamaların her yerinde. Bu derste, Compose'un liste oluşturmayı nasıl kolaylaştırdığını ve animasyon eklemeyi nasıl daha eğlenceli hale getirdiğini öğreneceksiniz.
Mesaj listesi oluşturma
Tek bir mesaj içeren bir sohbet biraz yalnız hissettirebilir. Bu yüzden sohbeti 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ında Compose'un
LazyColumn
ve
LazyRow
komutlarını kullanın. Bu composable'lar yalnızca ekranda görünen öğeleri oluşturduğundan uzun listelerde çok verimli olacak şekilde tasarlanmıştır.
Bu kod snippet'inde, LazyColumn
için bir items
alt öğesi olduğunu görebilirsiniz. Parametre olarak bir List
parametresi alır ve lambda'sı, Message
örneği olan message
adını verdiğimiz (istediğimiz adı vererek) bir parametre alır.
Kısacası, bu lambda sağlanan List
öğesinin her bir öğesi için çağrılır. Görüşmenin hızlı bir şekilde 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 gelmektedir. Şimdi animasyonlarla oynama zamanı! Hem içerik boyutunu hem de arka plan rengini canlandırarak mesajı genişletip daha uzun bir mesajı genişletme özelliği ekleyebilirsiniz. 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.
Birleştirilebilir işlevler remember
kullanarak yerel durumu belleğe depolayabilir ve mutableStateOf
öğesine iletilen değerde yapılan değişiklikleri izleyebilir. Bu durumu kullanan composable'lar (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 üzerinde yapılan değişiklikler 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 mesaj içeriğinin arka planını, tıkladığımız isExpanded
özelliğine göre değiştirebilirsiniz. composable'da 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 rengine animasyon eklemek için arka plan rengini MaterialTheme.colorScheme.surface
yerine MaterialTheme.colorScheme.primary
olacak şekilde kademeli olarak değiştirin. 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.