Search for:

Einführung von Jetpack Compose in das bestehende Projekt von Ziv Kesten | Februar 2022

Erstellen Sie mit “Erinnern” eine erweiterbare Statusansicht.

Ziv Kastanie
Bild von Ziv Kesten

Betrachten wir zunächst einen Einzelfall des Objekts, das wir bauen.

  • Text, der den Untertitel des Artikels enthält.
  • Rechtspfeil-Symbol (das animiert wird, sich vertikal zu drehen, wenn wir ein Element erweitern).
@Composable
ExpandableListItem() {
Card(...) {
Row(...) {
TitleAndSubtitle(...)
Icon(...)
}
}
}

Card ein vom System geliefertes Verbundbauteil ist, kann dies einige Zeit in Anspruch nehmenelevation ich shape als Parameter, und wir können es mit a versorgenmodifier für alles andere, was wir brauchen.
Der Card ist ein Container für unser erweiterbares Listenelement, damit wir es versenden elevation und einigemodifiers :

  • padding() – Es gibt uns Platz von den Rändern.
  • clip(RoundedCornerShape(*.dp)) – wird die Karte der gelieferten beifügen RoundedCornerShape .
  • clickable() – ergibt ein Lambda, das wir später zur Abwechslung verwenden können Zustand zusammengesetzt
Card(
elevation = 4.dp,
modifier = Modifier
.fillMaxWidth()
.padding(start = 15.dp, top = 15.dp, end = 15.dp)
.clip(RoundedCornerShape(8.dp))
.clickable { // We will deal with the click event later }
)

Bei uns Card wir haben Row (Horizontales Äquivalent LineraLayout), die Titel und ein Symbol enthält.

Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {...}

U Row legen wir fest TitleAndSubtitle ich Icon die horizontal ausgerichtet werden.

Row(...) {
TitleAndSubtitle(
title = "Expandable item title",
subtitle = "There are more items below! 👇"
)
Icon(...)
}
@Composable
fun TitleAndSubtitle(
title: String,
subtitle: String
) {
Column(verticalArrangement = Arrangement.Center) {
Text(text = title)
Text(text = subtitle)
}
}

Der Icon ist ein zusammenbaubares System, wir geben es ihm imageVector die wir als Teil der kompositorischen Abhängigkeit erhalten, an align Modifikator und etwas Neues, das wir noch nicht gesehen haben … a graphicsLayer.

Icon(
imageVector = Icons.Default.ArrowDropDown,
modifier = Modifier
.align(CenterVertically)
.graphicsLayer(...)
)

Der graphicsLayer Modifikator

GraphicsLayer ist ein Modifikator, der zum Anwenden von Effekten auf Inhalte verwendet wird, z. B. Skalierung, Drehung, Deckkraft, Schatten und Beschneidung.
In unserem Fall möchten wir das Pfeilsymbol so drehen, dass sich der Pfeil nach oben dreht, wenn das Element erweitert wird.

Icon(
modifier = Modifier
.graphicsLayer(
rotationZ = animateFloatAsState(
if (expanded) 180f else 0f).value,
)
)

In Jetpack Compose zeigt das deklarative UI-Framework wieder nur Elemente, die ihre eigenen hatten Kondition geändert, wenn wir darüber sprechen Kondition Im Zusammenhang mit der Compose-Benutzeroberfläche beziehen wir uns normalerweise speziell auf einige Funktionsvariablen, die enthalten oder darstellen Kondition.

@Composable
ExpandableListItem() {
var expanded by remember { mutableStateOf(false) }
Card(modifier = Modifier.clickable { expanded = !expanded}) {
Row(...) {
TitleAndSubtitle(...)
Icon(...)
}
}
}

mutableStateOf

Wir nehmen die Initialen Kondition das Objekt, das ist falsch (extended = false) und als Standard übergeben mutableStateOf:

mutableStateOf ist eine reaktive Strömung, ähnlich LiveDate oder StateFlow und wird boolesche Werte ausgeben, wenn wir uns ändern erweitert Variable.

merken

Wir wickeln mutableStateOf tok ua remember blockieren, damit es bei allen Neuzusammenstellungen nicht vergessen wird, sonst wird das Kondition wird die Voreinstellung sein falsch jedes Mal ExpandableListItem namens.

Jetzt müssen wir am Ende unserer Komponente einen weiteren Abschnitt hinzufügen,

@Composable
ExpandableListItem() {
var expanded
Card(...) {
/// Wrap the row in a Column
Column {
Row(...) {
TitleAndSubtitle(...)
Icon(...)
}

// And add the extra items sections
Column {
ExtraItem(item = Item())
ExtraItem(item = Item())

}
}
}
}
data class Item (
val title: String,
val date: String
)
@Composable
fun ExtraItem(item: Item) {
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Text(text = item.title)
Text(text = item.date)
}
}
//// Extra items sections

Divider(modifier = Modifier.height(1.dp))
Column(modifier = Modifier.padding(...)) {

Spacer(modifier = Modifier.height(10.dp))
ExtraItem(item = Item())

Spacer(modifier = Modifier.height(10.dp))
Divider(modifier = Modifier.height(1.dp))
Spacer(modifier = Modifier.height(10.dp))

ExtraItem(item = Item())

Spacer(modifier = Modifier.height(10.dp))
Divider(modifier = Modifier.height(1.dp))
Spacer(modifier = Modifier.height(10.dp))

ExtraItem(item = Item())

}

Eine der wunderbarsten Komponenten, die die Abhängigkeit vom Kompilieren einer Benutzeroberfläche beinhaltet, ist AnimatedVisibility zusammensetzbar.

@Composable
fun ExpandableListItem() {
var expanded by remember { mutableStateOf(false) }
Card() {
Row() {
TitleAndSubtitle()
Icon()
}
AnimatedVisibility(visible = expanded) {
Column {
ExtraItem(item = Item())
ExtraItem(item = Item())
}
}
}
}

Der AnimationSpec speichert die Animationsspezifikation, wir können sie verwenden, um sie zu definieren Genuss, Dauer, Verzögerungen, und andere Spezifikationen im Zusammenhang mit der Anpassung von Animationen.
Wenn wir Animationen wie z erweitern ich reduzieren Animationen für unsere Benutzeroberfläche können wir als verwenden.

AnimatedVisibility(
visible = expanded,
enter = expandVertically(
animationSpec = tween(
durationMillis = 300, easing = FastOutLinearInEasing)
)
,
exit = shrinkVertically(
animationSpec = tween(
durationMillis = 300, easing = FastOutLinearInEasing)
)

)

Wir haben heute viel gelernt! Wir haben den Pfeil mit animiert graphicsLayer Modifikator, mit dem wir die Sichtbarkeit animiert haben AnimatedVisibilityund wir haben gelernt, wie man es benutzt Kondition in Jetpack Compose mit remember ich mutableStateOf.

Android Jetpack Compose: Erstellen Sie ein Ersatzmaterialthema Lähde: Pedro Glória | Januar 2022

Wir haben also unser Thema definiert, wie können wir dieses neue Thema nun zu komponierenden Elementen wie einer Schaltfläche hinzufügen? Beim ersten Versuch habe ich folgendes gemacht:

Und das Ergebnis war:

Nun, das sieht nicht so aus, wie wir es in unserem Thema definiert haben. Nicht wahr? Also habe ich mir angesehen, wie die Schaltfläche in MaterialTheme definiert ist

Wie ich schnell lernte (was, ehrlich gesagt, vollkommen erwartet wurde, verstand ich nicht nur anfangs die Auswirkungen der Erstellung unseres eigenen Designs), verwendet Button MaterialTheme-Attribute, die wir nicht definiert haben. Das bedeutet dann, dass wir die Button-Attribute komplett durch unsere eigenen ersetzen müssen. Und das taten wir.

Was wiederum diese Schaltfläche erstellt

Ok, es sieht besser aus, aber die Typografie sieht komisch aus, oder? Also habe ich mir den Material-Button-Code angesehen und wir können Folgendes sehen:

Nun, es scheint unseren TextStyle mit MaterialTheme-Typografie zu überwältigen. Ok, wir können das beheben, indem wir unseren eigenen TextStyle hinzufügen. Also ersetzen wir unseren Text durch den folgenden Code, der das Endergebnis liefert

Okay! Jetzt sieht es aus wie einer unserer Buttons!

Wie wir bereits gelernt haben, müssen wir Compilation-Theme-Materialien mit unseren Theme-Attributen in unsere eigenen Compiler packen. Lassen Sie uns versuchen, eine Oberfläche zu schaffen, die zu dunklen und hellen Themen passt. Auf den ersten Blick könnten wir einfach das mitgelieferte Surface verwenden. Aber jetzt erwarten wir schon, dass die Dinge nicht so funktionieren, wie wir wollen, oder?

Das helle Thema sieht gut aus (aber ist es das wirklich?), aber das dunkle ist nichts im Vergleich zu dem, was wir erwartet haben. Es sieht überhaupt nicht düster aus! Aber jetzt wissen wir, was das Problem ist. Wenn wir uns noch einmal die Definition von Compose Surface ansehen, sehen wir Folgendes:

Ja. Verwendet MaterialTheme-Farben. Also lassen Sie es uns um unsere Oberfläche wickeln

Ja! Das wollen wir. Hier sind einige Dinge zu beachten.

  1. Wir haben die Hintergrundfarbe als Oberflächenfarbe definiert. Aber hier wird es interessant. Da Sie Ihr eigenes Thema definieren, können Sie frei entscheiden, welche Farbe Sie für Ihre Oberflächen wünschen, Sie können jedes Farbattribut verwenden, das Sie in Ihrem Thema definiert haben: Primär, Sekundär, Hintergrund, Oberfläche oder sogar Banane.
  2. Aufmerksamere Leser haben vielleicht bemerkt, dass wir unsere eigenen definieren InhaltFarbe wie defaultContentColorFor (Farbe) Was ist das?

MaterialTheme gibt uns die Methode, die ist contentColorFor (Farbe) aber wir können es nicht verwenden, weil es die MaterialTheme-Spezifikation verwendet, die zur MaterialTheme-Farbgebung zurückkehrt. Daher verwenden wir unsere Methode, um die Farben unseres Themas abzurufen

Durch die Verwendung unserer Komponentenelemente, die vordefinierte Komponenten umschließen, und durch das Ändern einiger Attribute, wie z. B. der Farbe, können wir unser Design vollständig anpassen und die korrekte Anwendung der Dark- und Light-Eigenschaften ermöglichen.

Ich hoffe, dass Sie mit diesem Wissen diese Logik auf jede gewünschte Komponente anwenden und Ihr eigenes brandneues benutzerdefiniertes Design erstellen können.

Oh verdammt! Testen Sie das Bild mit Jetpack Compose von Anders Ullnæss | Januar 2022

# beachbod2022

Screenshot-Tests (oder Screenshot-Tests, ich werde beide Begriffe abwechselnd verwenden) ist eine Art von Tests, die uns hilft sicherzustellen, dass sich unsere Benutzeroberfläche nicht unbeabsichtigt ändert.

Der Testschuss besteht aus 2 Schritten:

  1. Aufzeichnen
  2. Bestätigen Sie

Aufzeichnen

Wenn wir mit der Erstellung eines Teils der Benutzeroberfläche fertig sind, egal ob es sich um einen Vollbildmodus oder nur um eine Schaltfläche handelt, schreiben wir eine Testaufnahme und nehmen auf. Der Screenshot wird in unserem Quellcode gespeichert und definiert die Baseline für unsere Benutzeroberfläche.

Bestätigen Sie

Wir werden höchstwahrscheinlich später auf einen Code eingehen, der die Benutzeroberfläche von unserem ursprünglichen Screenshot ändern kann oder auch nicht.
Bei der Überprüfung nimmt die Testaufnahme einen neuen Screenshot auf und vergleicht die beiden Bilder. Wenn sie nicht identisch sind, schlägt unsere Testaufnahme fehl.

“Aber was, wenn ich daran denke, die Benutzeroberfläche zu ändern?” Ruiniert das nicht meine Testaufnahme?“
Ja er wird. Wenn wir die Benutzeroberfläche absichtlich ändern, erfassen wir nur erneut.
Als netter Bonus zeigt unsere Auszahlungsanfrage den Look vorher und nachher, was unsere bewerteten Freunde glücklich macht!

Wer hätte gedacht, dass Designer ihre Meinung ändern könnten?

Meiner Erfahrung nach ist das Testen von Videos bei iOS-Entwicklern sehr beliebt, und es wird selten von Android-Entwicklern gesprochen. Ich habe noch nie an Projekten gearbeitet, bei denen dies zuvor für Android durchgeführt wurde. Einer der Gründe könnte sein, dass das iOS-Tool fantastisch und einfach zu starten ist. (Meine Kollegen verwenden https://github.com/pointfreeco/swift-snapshot-testing). Nicht so sehr für Android, obwohl ich denke, dass sich die Dinge verbessern.

In jedem Fall haben wir uns von iOS-Kollegen inspirieren lassen und wollten es selbst ausprobieren. Wir haben auch mit der Arbeit an Jetpack Compose begonnen und dachten, es wäre schön, alle unsere neuen Compose-UI-Komponenten zu testen.

Der erste Schritt war, die richtige Bibliothek zu finden. Von den wenigen Bibliotheken fanden wir nur eine, die Compose erwähnte, also war es eine einfache Wahl:
https://github.com/pedrovgs/Shot

Für Grundlagen zum Schreiben eines Screenshot-Tests für Jetpack Compose lesen Sie hier den Blogbeitrag der Bibliothek:
https://blog.karumi.com/jetpack-compose-screenshot-testing-with-shot/

Da dieser Blogbeitrag bereits die Grundlagen behandelt, werde ich mich auf die zusätzlichen Schritte konzentrieren, die wir unternommen haben:

  1. Durchführung von Aufnahmetests im Rahmen von CI/CD
  2. Arbeiten Sie mit Screenshots, die auf verschiedenen Emulatorarchitekturen aufgenommen wurden
  3. Machen Sie Tests schnell und einfach zu schreiben

In unserem Projekt verwenden wir Bitrise für CI / CD, aber unser Ansatz sollte auch für andere Einstellungen funktionieren. Mit Shot führen Sie Screenshot-Tests durch die Gradle-Aufgabe durch ./gradlew internalDebugExecuteScreenshotTests wo internalDebug ist Ihre Variante der Herstellung.

Wenn Sie wie wir bereits einige UI-Tests haben, die keine Screenshots sind, müssen Sie etwas Spezifischeres einstellen. Wir tun dies, indem wir eine Namenskonvention verwenden und alle unsere Screenshot-Tests benennen *ScreenshotTest und führen Sie den Build-Befehl wie folgt aus:

./gradlew internalDebugExecuteScreenshots -Pandroid.testIntrumentationRunnerArguments.tests_regex=.*ScreenshotTest.*

Wenn Sie ihn lokal ausführen, wird dieser Befehl auf jedem Emulator oder Gerät ausgeführt, das Sie verwenden. Wenn Sie als Teil Ihres CI/CD arbeiten, müssen Sie zuerst einen Emulator erstellen und ausführen. In Bitrise haben Sie dafür einen netten AVD-Manager-Schritt:

Beim lokalen Erstellen von Screenshots ist es wichtig, denselben Emulatortyp zu verwenden, daher haben wir auch ein Skript zum Erstellen unseres Emulators mit dem entsprechenden Namen bissig. (Dies kann auch in anderen CIs / CDs ohne den AVD-Manager-Schritt verwendet werden):

Dieses Skript ist im Laufe der Zeit etwas gewachsen, um meinen Kollegen dabei zu unterstützen, einen neuen Mac mit Apple-Silikon zu bekommen (dazu später mehr), aber ein wichtiger Teil passiert in der letzten Zeile. Erstellt einen Emulator mit den gleichen Spezifikationen wie der von Bitrise.

Nach dem Schritt AVD Manager in Bitrise müssen Sie warten, bis der Emulator bereit ist, bevor Sie die Screenshot-Tests ausführen. Ich habe eine Weile gebraucht, um herauszufinden, warum es nicht funktioniert hat, da die Fehlermeldung, die Sie erhalten, nicht sehr klar ist.
Dazu gibt es natürlich einen Schritt:

Geduld ist eine Tugend

Wir führen dieses Skript lokal aus, um die Screenshots auszuführen (zu überprüfen):

Das Skript zum Erfassen von Screenshots ist sehr ähnlich, jedoch mit dem Capture-Parameter:

Beide verwenden dieses Skript, um den Emulator auszuführen:

Ich habe die Abbruchleitung des Emulators eingeschaltet, als die Tests vorbei waren. Ohne sie würden Sie einen neuen Emulator erhalten, der jedes Mal ausgeführt würde, wenn Sie das Skript ausführen (und Tests würden auf allen gleichzeitig ausgeführt).

Wir zahlen derzeit nicht für die schnellsten Maschinen in Bitrise, daher ist die Pipeline leider zu langsam (25-30 Minuten), um für jede Auszahlungsanforderung ausgeführt zu werden. Das Ausführen der Aufnahmen selbst ist nicht so schlimm, aber das Erstellen und Ausführen des Emulators ist ziemlich langsam. Wenn Sie den Emulator zuvor erstellt und ausgeführt haben, dauert es beim lokalen Start nur 1-2 Minuten, um unsere ~ 50 Tests auszuführen, und diese Zahl erhöht sich nicht wesentlich, wenn neue Tests hinzugefügt werden.

Anstelle jeder Auszahlungsanforderung führen wir die Pipeline jede Nacht aus und senden sie an den Teams-Kanal, wenn sie fehlschlägt. Nicht ideal, aber gut genug:

Vielleicht sollte ich unsere Testaufnahmen reparieren, anstatt Blogbeiträge zu schreiben?

Beim Vergleich von Screenshots, die auf Emulatoren mit unterschiedlichen Architekturen aufgenommen wurden, kann es Unterschiede geben, die für das menschliche Auge nicht sichtbar sind, aber unser Testbild wird trotzdem fehlschlagen. Auf dem neuen Apple-Silikon-Mac meines Kollegen kann kein x86_64-Emulator wie auf meinem älteren Mac oder dem Ubuntu-Docker-Image von Bitrice ausgeführt werden.

Unsere suboptimale Lösung dafür besteht darin, unseren Aufnahmetests etwas Toleranz hinzuzufügen. Wir lassen die Tests erfolgreich sein, wenn der Unterschied zwischen den beiden Screenshots weniger als 2 % beträgt.

Dies kann zu kleinen unbeabsichtigten Änderungen an der Benutzeroberfläche führen, die von Tests nicht erkannt werden. Dies kann ein echtes Problem sein und wir hatten bereits einige Fälle, in denen Screenshot-Tests keine Änderung in der Benutzeroberfläche festgestellt haben:

  1. Ändern Sie ein Symbol in den Vollbildmodus
  2. Es verändert die Marge ein wenig

Das Schreiben von Filmmaterialtests kann mühsam und repetitiv sein, daher möchten wir, dass sie einfach zu schreiben sind und sich nicht wie eine Verpflichtung anfühlen.

Mit Jetpack Compose erstellen wir regelmäßig Reviews unserer Komponenten, die unterschiedliche Konfigurationen zeigen.

Wenn wir Footage-Tests erstellen, wollen wir das Gleiche.
Also haben wir angefangen, Testaufnahmen unserer Bewertungen zu erstellen:

Mit der Philosophie, für jede Rezension einen Screenshot-Test zu machen, können wir sehen, dass alle Screenshots sehr ähnlich aussehen werden.

Fürs Erste haben wir eine Live-Vorlage in Android Studio erstellt, um sie schneller zu schreiben.

Schreiben Sie einfach einen Snap, drücken Sie auf die Registerkarte und geben Sie den Namen Ihrer Bewertung ein. Dies ist schneller, als sie jedes Mal von Hand zu schreiben, aber eine zusätzliche Verbesserung könnte darin bestehen, ein Skript zu erstellen, das einen Test für jede Überprüfungsnotiz generiert.

Das Testen der Aufzeichnung ist für Android immer noch etwas umfangreicher als für iOS, und die von uns verwendete Bibliothek hat keine großartige Integration mit Android Studio. Sie können einen Screenshot-Test nicht einfach mit der Wiedergabetaste ausführen / aufzeichnen, Sie müssen die Gradle-Aufgabe verwenden.

Der HTML-Bildverifizierungsbericht zeigt Ihnen, wenn Änderungen an Ihrer Benutzeroberfläche vorgenommen werden

Aber für mich machen diese Vorteile es immer noch wertvoll:

  1. Wir können sicher sein, dass sich unsere Benutzeroberfläche nicht unbeabsichtigt ändert
  2. Unsere Auszahlungsanträge erhalten nette Bewertungen der neuen UI, die wir vorgenommen haben, und der UI-Änderungen, die wir “kostenlos” vorgenommen haben.
  3. Wir können aufhören, die Art von Espresso-Tests zu schreiben, die prüfen, ob alle Elemente der Benutzeroberfläche auf dem Bildschirm angezeigt werden
Ich werde das nicht vermissen

Hinterlasse einen Kommentar oder kontaktiere mich, wenn du einen Snapchat haben möchtest. Wenn Sie Fragen oder Verbesserungsvorschläge zu unserem eigenen Setup haben oder Hilfe beim Einrichten für Ihr eigenes Projekt benötigen. Hier oder auf Twitter: https://twitter.com/andersullnass.

Danke an Alex von der niederländischen Android-Slack-Benutzergruppe (https://twitter.com/alex_caskey) für die großartige Hilfe, als ich dies ursprünglich gepostet habe, und vielen Dank an meinen Kollegen Cristan, der mit mir daran gearbeitet hat, die Art und Weise, wie wir die Aufnahmen testen, zu verbessern, und für die Überprüfung dieses Blog-Beitrags.

Erste Schritte mit ConstraintLayout in Jetpack Compose | von Shrey Sindher | Januar 2022

Shrey Sindher
Autor des Fotos Hal Gatewood er Unsplash

Jetpack Compose ist ein moderner Satz von Tools für Android zum Erstellen einer nativen Benutzeroberfläche. Vereinfacht und beschleunigt die Entwicklung der Benutzeroberfläche auf Android. Beleben Sie Ihre App schnell mit weniger Code, leistungsstarken Tools und intuitiven Kotlin-APIs.

Ich habe kürzlich Jetpack Compose gelernt und fast sofort den Wahnsinn dahinter erkannt. Mit Compose können Sie im Vergleich zur Verwendung von Android View mit weniger Code mehr erreichen: Schaltflächen, Listen oder Animationen – was auch immer Sie tun müssen, Sie müssen jetzt weniger Code schreiben.

Ich habe ConstraintLayout oft in meinen Projekten verwendet. Als ich zu Compose wechselte, hatte ich natürlich das Bedürfnis, es auch hier zu erkunden. Hier sind also die Entwürfe, die wir umsetzen werden:

Inspiration: https://proandroiddev.com/designing-complex-ui-using-android-constraintlayout-cb0606823da0

In diesem Leitfaden behandeln wir Folgendes zu ConstraintLayout:

  1. Grundlagen
  2. Richtlinien
  3. Barrieren
  4. Ketten
  1. Öffnen Sie Android Studio und klicken Sie auf Neues Projekt.
  2. Wählen Leeren Sie die Montageaktivität. Klicke auf Nächste.

3. Geben Sie Ihrem Projekt den passenden Namen und klicken Sie auf Beenden.

4. Wenn das Projekt vollständig geladen ist, gehen Sie zur Gradle-Datei auf Anwendungsebene und darunter Sucht, hinzufügen:

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0"

5. Synchronisieren Sie Gradle-Projektdateien.

gehen MainActivity.kt und ersetzen Sie den Code durch:

Erstellen Sie eine neue Klasse: MovieBookingScreen.kt. Und fügen Sie den folgenden Code hinzu:

Hier erstellen wir zunächst eine grundlegende Compositing-Funktion mit nichts als a Surface ia ConstraintLayout die die gesamte Höhe und Breite abdeckt.

Zum Vergleich mit einem herkömmlichen XML-basierten ConstraintLayout weisen wir unseren Ansichten IDs zu und verwenden diese IDs dann, um andere Ansichten entsprechend einzuschränken. Und hier erstellen wir zuerst all diese Referenzen mit createRefs() Funktion und ordnen Sie diese dann unseren Komponenten zu.

Nehmen wir zunächst das Menüsymbol in der oberen linken Ecke. Wir gebrauchen constrainAs(reference) um dem Komponierten eine Referenz zuzuweisen. Und dann u constrainBlock, schreiben wir alle Einschränkungen. Im folgenden Beispiel weisen wir zu menuButton Unter Bezugnahme auf das kompatible Symbol definieren wir in constrainBlock seine Einschränkungen:

Anfang ich oben verbunden sein soll Eltern Anfang ich oben das heißt mit 16 dps-Margen

Anstelle des übergeordneten Elements können wir auf andere zusammengesetzte Referenzen verweisen.

Richtlinie

Die Richtlinien in ConstraintLayout sind unsichtbare Linien, die für Benutzer nicht sichtbar sind, aber Entwicklern dabei helfen, das Layout einfach zu gestalten und die Ansicht dieser Richtlinien einzuschränken, sodass das Design klarer und interaktiver sein kann.

Nehmen wir als Nächstes an, wir möchten eine Richtlinie auf 40 % erstellen und das Titelbild des Films zwischen der übergeordneten und der Richtlinie begrenzen. Wir möchten auch sicherstellen, dass die Breite und Höhe des Bildes 2: 3 betragen.

Wir können Folgendes tun, indem wir zuerst eine Richtlinie erstellen. (40 % werden als 0,4f übertragen). Wir können auch den absoluten Wert weitergeben dp. Dann definieren wir die Breite als Dimension.fillToConstraints das ist analog zum tunen android:layout_width=”0dp” . Wir verwenden, um das Verhältnis einzustellen aspectRatio Modifikator, wo wir das Verhältnis übertragen. Das ist wieder analog app:layout_constraintDimensionRatio=”2:3" .

Ebenso können wir andere Texte erstellen, die komponiert und begrenzt werden können.

Horizontale Verkettung

Eine Kette ist eine Gruppe von Ansichten, die durch bidirektionale Positionsbeschränkungen miteinander verbunden sind

Die Kette kann von 3 Arten sein:

  1. Spread: Ein Kettenstil, der die enthaltenen Layouts gleichmäßig verteilt.
  2. SpreadInside: Ein Kettenstil, bei dem die erste und die letzte Anordnung an die Beschränkungen an jedem Ende der Kette angehängt werden und der Rest gleichmäßig verteilt wird.
  3. Packed: Der Kettenstil, in dem die Zeitpläne enthalten sind, wird zusammengepackt und in der Mitte des verfügbaren Platzes platziert.
Macht einen Teil unseres Looks aus

Als Nächstes erstellen wir für die Besetzungslinie zunächst ein ConstraintLayout, fügen unsere zusammengesetzten hinzu und führen sie dann mit zusammen createHorizontalChain(). Außerdem ist jedes Bild, das zusammengesetzt werden kann, durch die Angabe eines Verhältnisses von begrenzt 1:1 um eine quadratische Form beizubehalten.

Barriere

Die Barriere verweist auf mehrere Widgets als Eingabe und erstellt eine virtuelle Richtlinie basierend auf dem extremsten Widget auf der angegebenen Seite. Beispielsweise wird die linke Barriere links von allen referenzierten Ansichten ausgerichtet.

Eine Barriere kann wie unten gezeigt einfach erstellt werden, indem Sie zu den Ansichten gehen. Hier schaffen wir die untere Barriere, um unter dem Titelbild und unserem Gussbehälter Orientierung zu bekommen. In ähnlicher Weise können wir eine obere, untere, anfängliche und endgültige Barriere erstellen.

val barrier = createBottomBarrier(coverImage, castContainer)

Als nächstes begrenzen wir den Text der Beschreibung unterhalb der Barriere. Damit sind wir mit der oberen Hälfte unseres Looks fertig 🎉. Jetzt bleibt uns die untere Hälfte des Bildschirms.

Teilen Sie die untere Hälfte des Bildschirms in 3 Teile:

  1. Kalenderleiste
  2. Details zum Kino
  3. Schaltfläche “Tickets buchen”.

Erstens kann ein grauer Hintergrund implementiert werden, indem eine einfache zu komponierende Oberfläche hinzugefügt und ihr eine graue Farbe gegeben wird.

1. Kalenderleiste

Die Kalenderleiste kann wiederum in drei Teile unterteilt werden: Voter, Datumsreihenfolge und Tagesreihenfolge.

Zuerst erstellen wir Text Composables für Tagesreihen und begrenzen Sie sie mit einer horizontalen Kette, um sie gleichmäßig über die Breite des Bildschirms zu verteilen. Dann erstellen wir Text Compoasables für die Datumslinie und begrenzen jedes Datum auf den entsprechenden Tag (Start und Ende) und das vorherige Datum (oben und unten), etwa so:

Jetzt kommt der interessante Teil. Wir erstellen zwei für die Datumsauswahl Surface zusammensetzbar. Ein weißer Streifen, der den Haupthintergrund darstellt, und der andere schwarze Streifen, der auf die weiße Fläche beschränkt ist. Da wir nun möchten, dass die Datumsauswahl dynamisch ist und sich zum ausgewählten Datum bewegt, speichern wir sie im Status, anstatt die Einschränkungen für den Beginn und das Ende des ersten Tages fest zu codieren. Wann immer wir also den Wert eines Zustands ändern, a recomposition wird ausgeführt, und unsere Datumsauswahl ändert ihre Grenzen entsprechend.

Sehen Sie sich als Beispiel den Composable-Clip unten aus dem Text „Montag“ an. U clickable Block ändern wir den Wert der Einschränkung des Datumsauswahlbereichs.

2. Kinodetails

Der Name des Kinos und die Entfernung können als zwei zusammengesetzte Texte betrachtet werden, die in der Mitte des verfügbaren Raums zwischen Kalenderleiste und Schaltfläche verbunden sind. Also erstellen wir einen ConstraintLayout-Compiler neu, der den gesamten verfügbaren Platz einnimmt, und verknüpfen beide Texte, die kompiliert werden können, mit VerticalChainBeibehaltung des Kettenstils als Packed.

3. Schaltfläche „Tickets buchen“.

Dies ist nur eine einfache Schaltfläche, die mit Text komponiert werden kann, der darin komponiert werden kann. Es ist auf die Unterseite des Elternteils begrenzt und so konzipiert, dass es die gesamte Breite einnimmt.

Und das ist es 😎

Folgendes haben wir erreicht:

Hier ist der vollständige Code MovieBookingScreen.kt für ihre referenz:

Danke fürs Lesen. Ich würde gerne alle Ihre Probleme besprechen und lösen. Wenn dir der Artikel gefallen hat, applaudiere und teile ihn 🙃

Einführung in Jetpack DataStore von Simona Stojanovic Android-Entwickler Januar 2022

Simona Stojanovic

Datenspeicher ist eine Jetpack-Datenspeicherbibliothek, die eine sichere und konsistente Möglichkeit bietet, kleine Datenmengen wie Einstellungen oder Anwendungsstatus zu speichern. Es basiert auf Kotlin Korutine und Flow die eine asynchrone Datenspeicherung ermöglichen. Es zielt darauf ab, zu ersetzen SharedPreferences, weil es sicher ist und nicht blockiert. Es bietet zwei verschiedene Implementierungen: Proto-DataStoredas typisierte Objekte speichert (unterstützt von Protokollpuffer) ich DataStore-Einstellungen, die Schlüssel/Wert-Paare speichert. Machen wir weiter, wenn wir es einfach benutzen DataStoregilt dies für beide Implementierungen, sofern nicht anders angegeben.

Wir werden uns diesen Blogbeitrag genauer ansehen Datenspeicher – wie es funktioniert, welche Implementierungen es bietet und ihre individuellen Anwendungsfälle. Wir werden uns auch ansehen, welche Vorteile und Verbesserungen es bringt SharedPreferences und warum sich der DataStore dadurch lohnt.

Schauen wir uns einen direkten Vergleich zwischen an SharedPreferences und Datenspeicher:

Vergleich von DataStore-Implementierungen mit SharedPreferences

Asynchrone API

Synchronbetrieb

Es ist jedoch möglich, DataStore und synchronen Betrieb mit ein wenig Hilfe des Corutin-Builders zu kombinieren, wie wir später sehen werden.

Fehlerbehandlung

Sicherheitsstufe

Datenkonsistenz

Migrationsunterstützung

Einstellungen Datenspeicher liest und schreibt datenbasiert Schlüssel/Wert-Paare, ohne vorherige Definition der Regelung. Auch wenn das vielleicht ähnlich klingt SharedPreferences, denken Sie an alle oben genannten Verbesserungen, die der DataStore mit sich bringt. Lassen Sie sich nicht von ihrem Teilen täuschen.”Einstellungen„Bei der Benennung – sie haben nichts gemeinsam und kommen von zwei völlig getrennten APIs.

Proto Datenspeicher Geschäfte getippte Objektemit Unterstützung Protocol Buffers, bietet Typsicherheit und eliminiert die Notwendigkeit von Schlüsseln. Protobuffs sind schneller, kleiner, einfacher und weniger mehrdeutig als XML und andere ähnliche Datenformate. Wenn Sie sie noch nie benutzt haben, haben Sie keine Angst! Dies ist sehr einfach zu lernen. Obwohl der Proto DataStore erfordert, dass Sie einen neuen Serialisierungsmechanismus erlernen, sind wir von seinen Vorteilen besonders überzeugt Typ Sicherheites ist es wert.

Vergleich von DataStore-Implementierungen

Bei der Wahl zwischen den beiden müssen Sie Folgendes berücksichtigen:

  • Wenn Sie mit arbeiten Schlüssel/Wert-Paare zum Lesen und Schreiben von Daten, die Sie möchten schnell migrieren von SharedPreferences mit minimalen Änderungen, während Sie immer noch die Vorteile von DataStore-Verbesserungen nutzen und sich ohne Typsicherheitsprüfungen sicher genug fühlen, können Sie mit gehen DataStore-Einstellungen
  • Wenn Sie Protokollpuffer für den zusätzlichen Vorteil einer verbesserten Lesbarkeit lernen möchten, wenn Ihre Daten Arbeit erfordern komplexere Klassenwie Aufzählungen oder Listen, und die Sie haben möchten vollständige Sicherheit unterstützen, während Sie dies tun, können Sie versuchen Proto-DataStore

Wenn Sie mit arbeiten müssen komplexe Datensätze größer als ein paar 10 KB ist, ist es sehr wahrscheinlich, dass Sie es brauchen werden Teilaktualisierungen oder Referenzintegrität zwischen verschiedenen Datentabellen. In diesem Fall sollte der Einsatz erwogen werden Zimmer.

Wenn Sie jedoch mit arbeiten kleiner und einfacher Datensätzewie z. B. Anwendungseinstellungen oder Status, und daher keine Teilaktualisierungen oder Referenzintegrität erfordern, sollten Sie auswählen Datenspeicher.

So wählen Sie zwischen DataStore und Room