Lektion 1: Zusammensetzbare Funktionen
Jetpack Compose basiert auf zusammensetzbaren Funktionen. Mit diesen Funktionen können Sie
App-Benutzeroberfläche programmatisch erstellen, indem sie ihr Aussehen
beschreibt und Datenabhängigkeiten bereitstellt,
anstatt sich auf die Konstruktion der Benutzeroberfläche (Initialisieren eines Elements,
Anhängen an Eltern usw.). Um eine zusammensetzbare Funktion zu erstellen, fügen Sie
@Composable
zum Funktionsnamen hinzu.
Textelement hinzufügen
Laden Sie zunächst die neueste Version von herunter. Android Studio und erstellen Sie eine App, indem Sie Neues Projekt auswählen Wählen Sie in der Kategorie Smartphone und Tablet die Option Leere Aktivität aus. Nennen Sie die App ComposeTutorial und klicken Sie auf Finish (Fertigstellen). Standardeinstellung enthält bereits einige Compose-Elemente, aber in dieser Anleitung erstellen Sie sie. Schritt für Schritt an.
Zeigen Sie zuerst eine „Hallo Welt!“- indem Sie ein Textelement in den
onCreate
-Methode. Dazu definieren Sie
und der Aufruf der Methode
Text
zusammensetzbare Funktion. Die
Der setContent
-Block definiert das Layout der Aktivität,
werden zusammensetzbare Funktionen aufgerufen. Zusammensetzbare Funktionen können nur aus anderen zusammensetzbaren Funktionen aufgerufen werden
Funktionen.
Jetpack Compose verwendet ein Kotlin-Compiler-Plug-in, um diese zusammensetzbaren Funktionen in die
Elemente der Benutzeroberfläche der App. Beispiel: Die zusammensetzbare Funktion Text
die in der Compose-UI-Bibliothek definiert wird, zeigt eine Textbeschriftung auf dem Bildschirm an.
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!") } } }
Zusammensetzbare Funktion definieren
Fügen Sie die Anmerkung @Composable
hinzu, um eine Funktion zusammensetzbar zu machen.
Um dies auszuprobieren, definieren Sie eine MessageCard
-Funktion, die
einen Namen übergeben und zum Konfigurieren des Textelements verwendet.
// ... 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!") }
Vorschau der Funktion in Android Studio ansehen
Mit der Annotation @Preview
können Sie eine Vorschau Ihrer zusammensetzbaren Funktionen in Android ansehen.
ohne die App erstellen und auf einem Android-Gerät oder Emulator installieren zu müssen. Die
Annotation muss für eine zusammensetzbare Funktion verwendet werden, die keine Parameter akzeptiert. In diesem Fall
Sie können die Funktion MessageCard
nicht in der Vorschau anzeigen.
. Erstellen Sie stattdessen eine zweite Funktion namens
PreviewMessageCard
, die einen Aufruf an
MessageCard
durch einen entsprechenden Parameter. Fügen Sie den
@Preview
Anmerkung vor dem
@Composable
.
// ... import androidx.compose.ui.tooling.preview.Preview @Composable fun MessageCard(name: String) { Text(text = "Hello $name!") } @Preview @Composable fun PreviewMessageCard() { MessageCard("Android") }
Erstellen Sie Ihr Projekt neu. Die App selbst ändert sich nicht, da die neue
Die PreviewMessageCard
-Funktion wird nirgendwo aufgerufen,
In Android Studio wird jedoch ein
Vorschaufenster hinzugefügt, das Sie maximieren können,
Design-/Codeansicht. Dieses Fenster zeigt eine Vorschau der UI-Elemente, die mit zusammensetzbaren Funktionen erstellt wurden.
Funktionen, die mit der Anmerkung @Preview
gekennzeichnet sind. Zum Aktualisieren
können Sie jederzeit oben im Vorschaufenster auf die Schaltfläche zum Aktualisieren klicken.
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") }
Lektion 2: Layouts
UI-Elemente sind hierarchisch, wobei die Elemente in anderen Elementen enthalten sind. In „Schreiben“ können Sie Erstellen Sie eine UI-Hierarchie, indem Sie zusammensetzbare Funktionen aus anderen zusammensetzbaren Funktionen aufrufen.
Mehrere Texte hinzufügen
Sie haben bereits Ihre erste zusammensetzbare Funktion und eine Vorschau erstellt. Weitere Jetpack Compose-Funktionen entdecken können Sie einen einfachen Bildschirm mit einer Liste von Nachrichten erstellen, können mit einigen Animationen erweitert werden.
Beginnen Sie damit, die Nachricht komponierbarer zu machen, indem Sie den Namen des Autors und ein
Nachrichteninhalt. Zunächst müssen Sie den zusammensetzbaren Parameter so ändern, dass er
Message
-Objekts anstelle eines
String
und fügen Sie weitere hinzu
Text
zusammensetzbare Funktion im
MessageCard
zusammensetzbar. Achten Sie darauf, die Vorschau zu aktualisieren.
.
// ... 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!") ) }
Mit diesem Code werden zwei Textelemente innerhalb der Inhaltsansicht erstellt. Da Sie jedoch keine werden die Textelemente übereinander gezeichnet, sodass der Text unlesbar wird.
Spalte verwenden
Die <ph type="x-smartling-placeholder"></ph>
Column
können Sie Elemente vertikal anordnen.
Column
hinzufügen zu:
MessageCard
.
Sie können
Row
, um Elemente horizontal und
<ph type="x-smartling-placeholder"></ph>
Box
, um Elemente zu stapeln.
// ... import androidx.compose.foundation.layout.Column @Composable fun MessageCard(msg: Message) { Column { Text(text = msg.author) Text(text = msg.body) } }
Bildelement hinzufügen
Fügen Sie Ihrer Nachrichtenkarte ein Profilbild des Absenders hinzu. Verwenden Sie die Methode
Resource Manager
um ein Bild aus der Fotogalerie zu importieren, oder verwenden Sie dieses Foto. Fügen Sie ein
Row
zusammensetzbar, um ein gut strukturiertes Design und eine
<ph type="x-smartling-placeholder"></ph>
Image
zusammensetzbar.
// ... 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) } } }
Layout konfigurieren
Ihr Mitteilungslayout hat die richtige Struktur, aber die Elemente sind nicht gut verteilt und das Bild ist zu groß! In „Compose“ werden Modifikatoren verwendet, um eine zusammensetzbare Funktion zu dekorieren oder zu konfigurieren. Sie können Sie Größe, Layout und Aussehen der zusammensetzbaren Funktion ändern oder indem Sie z. B. ein Element anklickbar machen. Sie können sie verketten, um umfangreichere zusammensetzbare Funktionen zu erstellen. Sie nutzen um das Layout zu verbessern.
// ... 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) } } }
Lektion 3: Material Design
Die Funktion „Compose“ wurde entwickelt, um Material Design-Prinzipien zu unterstützen. Viele der zugehörigen UI-Elemente Sofort einsatzbereites Material Design. In dieser Lektion gestalten Sie Ihre App mit Material Design. Widgets.
Material Design nutzen
Ihr Mitteilungsdesign hat jetzt ein Layout, aber es sieht noch nicht besonders gut aus.
Jetpack Compose bietet eine Implementierung von Material Design 3 und seiner UI-Elemente aus dem
. Dadurch wird das Aussehen unseres MessageCard
verbessert.
mit Material Design-Stilen zusammensetzbar.
Verpacken Sie zuerst die MessageCard
-Funktion mit dem
Das Materialthema wurde in deinem Projekt „ComposeTutorialTheme
“ erstellt.
sowie ein Surface
.
Tun Sie dies sowohl im @Preview
als auch im
setContent
. Dann können Ihre zusammensetzbaren Funktionen
, um die im Design Ihrer App definierten Stile zu übernehmen und so für Konsistenz in Ihrer App zu sorgen.
Material Design basiert auf drei Säulen: Color
,
Typography
und Shape
.
Sie werden sie einzeln hinzufügen.
Hinweis:Durch die Vorlage zum Erstellen einer leeren Schreibaktivität wird ein Standarddesign für Ihr Projekt erstellt, das
ermöglicht das Anpassen von
MaterialTheme
.
Wenn Sie Ihrem Projekt einen anderen Namen
ComposeTutorial erstellen, finden Sie Ihr benutzerdefiniertes Design in der
Theme.kt
-Datei im
Teilpaket 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!") ) } } }
Farbe
Verwenden Sie MaterialTheme.colorScheme
, um Stile mit Farben aus der
umschlossenes Design. Sie können diese Werte aus dem Design überall dort verwenden, wo eine Farbe benötigt wird. In diesem Beispiel werden dynamische Designfarben verwendet (definiert durch die Geräteeinstellungen).
Sie können dynamicColor
in der Datei MaterialTheme.kt
auf false
festlegen, um dies zu ändern.
Gestalten Sie den Titel und fügen Sie dem Bild einen Rahmen hinzu.
// ... 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) } } }
Typografie
Material Typografie-Stile sind verfügbar in MaterialTheme
,
fügen Sie sie einfach den Text
zusammensetzbaren Funktionen hinzu.
// ... @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 ) } } }
Form
Mit Shape
können Sie den letzten Schliff geben. Verpacken Sie zuerst die
um ein
<ph type="x-smartling-placeholder"></ph>
Surface
zusammensetzbar. Dadurch können Sie die
Form und Höhe des Nachrichtentexts. Zur Verbesserung des Layouts wird der Mitteilung auch ein Abstand hinzugefügt.
// ... 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 ) } } } }
Dunkles Design aktivieren
Dunkles Design oder den Nachtmodus aktivieren, um ein helles Display zu vermeiden, oder um des Geräteakkus. Dank Material Design-Unterstützung kann Jetpack Compose auch bei aus. Mit den Farben, Texten und Hintergründen von Material Design an den dunklen Hintergrund anpassen.
Sie können in Ihrer Datei mehrere Vorschauen als separate Funktionen erstellen oder mehrere Annotationen derselben Funktion zuordnen.
Fügen Sie eine neue Vorschauanmerkung hinzu und aktivieren Sie den Nachtmodus.
// ... 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!") ) } } }
Die Farbauswahl für das helle und das dunkle Design wird in der IDE-generiert:
Theme.kt
-Datei.
Bisher haben Sie ein UI-Element für Nachrichten erstellt, das ein Bild und zwei Texte mit unterschiedlichen und sieht sowohl in einem hellen als auch in einem dunklen Design gut aus.
// ... 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!") ) } } }
Lektion 4: Listen und Animationen
Listen und Animationen sind überall in Apps zu finden. In dieser Lektion erfahren Sie, wie Sie können Sie Listen erstellen und Animationen hinzufügen.
Liste mit Mitteilungen erstellen
Ein Chat mit einer Nachricht fühlt sich ein wenig einsam an, daher werden wir das Gespräch ändern und mehr als
eine Nachricht. Sie müssen eine Conversation
-Funktion erstellen
in der mehrere Nachrichten angezeigt werden. Verwenden Sie für diesen Anwendungsfall die
<ph type="x-smartling-placeholder"></ph>
LazyColumn
und
<ph type="x-smartling-placeholder"></ph>
LazyRow
Diese zusammensetzbaren Funktionen rendern
nur die Elemente,
die auf dem Bildschirm sichtbar sind. Sie sind daher für lange Listen sehr effizient.
In diesem Code-Snippet sehen Sie, dass LazyColumn
ein
items
Kind. Es dauert eine Weile,
List
als Parameter und seine Lambda-Funktion
erhält einen Parameter namens message
.
benannt haben, nämlich eine Instanz von Message
.
Kurz gesagt: Dieses Lambda wird für jedes Element der bereitgestellten
List
Kopieren Sie die
Beispiel-Dataset
in Ihr Projekt integrieren, um das Gespräch schnell zu starten.
// ... 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) } }
Nachrichten beim Maximieren animieren
Die Unterhaltung wird interessanter. Es ist Zeit, mit Animationen zu spielen! Sie werden
Die Möglichkeit, eine Nachricht zu erweitern, um eine längere zu zeigen, indem sowohl die Inhaltsgröße als auch die
die Hintergrundfarbe. Um diesen lokalen UI-Status zu speichern, müssen Sie überprüfen, ob eine Nachricht
maximiert wurden oder nicht. Um diese Statusänderung nachzuverfolgen, müssen Sie die Funktionen verwenden
remember
und
mutableStateOf
.
Zusammensetzbare Funktionen können den lokalen Status mithilfe von
remember
und verfolgen Sie Änderungen am Wert, der an
mutableStateOf
. Composables (und ihre untergeordneten Elemente) mit
wird dieser Status automatisch neu gezeichnet, wenn der Wert aktualisiert wird. Dies wird als
recomposition um.
Mit den State APIs von Compose wie remember
und
mutableStateOf
– bei allen Statusänderungen wird die UI automatisch aktualisiert.
Hinweis:Sie müssen die folgenden Importe hinzufügen, um die
Syntax für delegierte Properties (das Schlüsselwort by
). Mit Alt + Eingabetaste oder Wahltaste + Eingabetaste werden sie hinzugefügt.
für Sie.
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 ) } } } }
Sie können jetzt den Hintergrund des Nachrichteninhalts
isExpanded
, wenn wir auf eine Nachricht klicken. Sie verwenden das
clickable
-Modifikator zur Verarbeitung von Click-Events im
zusammensetzbar sind. Statt einfach die Hintergrundfarbe der Seite
Surface
, animieren Sie die Hintergrundfarbe mit
Ändern des Werts schrittweise von
MaterialTheme.colorScheme.surface
bis
MaterialTheme.colorScheme.primary
und umgekehrt. Gehen Sie dazu wie folgt vor:
verwenden Sie die Funktion animateColorAsState
. Schließlich haben Sie
verwendet den animateContentSize
-Modifikator zur Animation des
die Größe des Nachrichtencontainers reibungslos:
// ... 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 ) } } } }
Nächste Schritte
Herzlichen Glückwunsch! Sie haben die Anleitung zum Schreiben einer Nachricht abgeschlossen. Sie haben einen einfachen Chatbildschirm erstellt, der effizient eine Liste von maximierbaren und animierten Nachrichten mit einem Bild und Text enthält. Diese wurden nach Material Design-Prinzipien mit einem dunklen Design und Vorschauen gestaltet – und das alles in weniger als 100 Codezeilen.
Sie haben bisher Folgendes gelernt:
- Zusammensetzbare Funktionen definieren
- Verschiedene Elemente in einer zusammensetzbaren Funktion hinzufügen
- UI-Komponente mit zusammensetzbaren Layout-Layouts strukturieren
- Zusammensetzbare Funktionen mithilfe von Modifikatoren erweitern
- Listen effizient erstellen
- Nachverfolgen des Status und Änderung
- Nutzerinteraktion zu einer zusammensetzbaren Funktion hinzufügen
- Maximieren und Animieren von Botschaften
Weitere Informationen zu einigen dieser Schritte finden Sie in den folgenden Ressourcen.