Android Kotlin Fundamentals 01.3: Image-Ressourcen und Kompatibilität

Dieses Codelab ist Teil des Android Kotlin Fundamentals-Kurss. Sie profitieren von diesem Kurs, wenn Sie nacheinander die Codelabs durcharbeiten. Alle Kurs-Codelabs finden Sie auf der Landingpage für Kotlin-Grundlagen für Android-Entwickler.

Einführung

In diesem Codelab erweiterst du die DiceRoller App aus dem letzten Codelab und erfährst, wie du in deiner App Bildressourcen hinzufügen und verwenden kannst. Außerdem lernst du, wie die App mit verschiedenen Android-Versionen kompatibel ist und wie Android Android Jetpack dabei helfen kann.

Wichtige Informationen

  • Hier erfahren Sie, wie Sie ein neues App-Projekt erstellen und eine App auf einem Emulator oder einem physischen Gerät ausführen.
  • Die grundlegenden Komponenten eines App-Projekts, einschließlich des Ressourcenverzeichnisses (res) und der Gradle-Build-Dateien.
  • So bearbeitest du die Layoutdatei der App.
  • Ansichtsobjekte im App-Code suchen und ändern

Lerninhalte

  • So fügst du Dateien zu deinen App-Ressourcen hinzu.
  • So verwenden Sie Bilder im Layout Ihrer App.
  • Wie du Aufrufe im App-Code effizienter findest
  • Platzhalterbilder im App-Design mit XML-Namespaces verwenden
  • Informationen zu Android-API-Levels für Ihre App und zu den möglichen Mindest-, Ziel- und kompilierten API-Levels.
  • Jetpack-Bibliotheken in Ihrer App für ältere Android-Versionen

Vorgehensweise

  • Ändern Sie die DiceRoller App im letzten Codelab und fügen Sie statt des Zahles Bilder für den Wert hinzu.
  • Fügen Sie Ihren App-Ressourcen Bilddateien hinzu.
  • Aktualisieren Sie das Layout und den Code der App, um Bilder für den Wert anstelle einer Zahl zu verwenden.
  • Aktualisiere deinen Code, um Aufrufe effizienter zu finden.
  • Aktualisiere deinen Code, damit beim Starten der App ein leeres Bild verwendet wird.
  • Aktualisiere deine App, um die Android Jetpack-Bibliotheken zur Abwärtskompatibilität mit älteren Android-Versionen zu verwenden.

In diesem Codelab bauen Sie auf der DiceRoller App auf, die Sie im vorherigen Codelab gestartet haben, und fügen würfelige Bilder hinzu, die sich nach dem Rollieren des Würfels ändern. Die endgültige DiceRoller-Anwendung sieht dann so aus:

Falls Sie nicht mit dem letzten Codelab gearbeitet haben, können Sie die Start-App hier herunterladen: DiceRoller.

Am Ende des letzten Codelabs gab es eine App, die jedes Mal, wenn der Nutzer auf eine Schaltfläche tippt, eine Textansicht mit einer Zahl zwischen 1 und 6 aktualisiert. Die App heißt jedoch DiceRoller, kein 1-6-Zahlgenerator. Es wäre also toll, wenn der Würfel richtig würfelt. Für diese Aufgabe fügen Sie Ihrer App Würfelbilder hinzu. Statt Text zu aktualisieren, wenn die Taste gedrückt wird, tauschen Sie in jedem Roll-Ergebnis ein anderes Bild aus.

Schritt 1: Bilder hinzufügen

  1. Öffnen Sie das DiceRoller-Projekt in Android Studio, falls es noch nicht vorhanden ist. Wenn Sie nicht mit dem letzten Codelab gearbeitet haben, können Sie die App hier herunterladen: DiceRoller.
  2. Maximieren Sie in der Projektansicht für Projekte den Ordner res und maximieren Sie dann drawable.



    Deine App verwendet viele verschiedene Ressourcen, wie Bilder, Symbole, Farben, Strings und XML-Layouts. Alle diese Ressourcen werden im Ordner res gespeichert. Im Ordner drawable sollten Sie alle Image-Ressourcen für Ihre App speichern. Die Ressourcen für das Launcher-Symbol der App sind bereits im Ordner drawable enthalten.
  3. Klicken Sie doppelt auf ic_launcher_background.xml. Dies sind XML-Dateien, in denen das Symbol als Vektorbild beschrieben wird. Mit Vektoren können Sie Bilder in vielen verschiedenen Größen und Auflösungen zeichnen. Bitmap-Bilder wie PNG oder GIF müssen unter Umständen für verschiedene Geräte skaliert werden. Das kann zu Qualitätsverlusten führen.
  4. Klicken Sie in der rechten Spalte des XML-Editors auf Vorschau, um die Vektorgrafik visuell darzustellen.


  5. Laden Sie die Würfelbilder für Ihre App von DiceImages.zip herunter. Entpacken Sie das Archiv. Ein Ordner mit XML-Dateien sollte in etwa so aussehen:

  1. Klicken Sie oben in der Projektansicht in Android Studio auf das Drop-down-Menü Android und wählen Sie Projekt aus. Der folgende Screenshot zeigt die Struktur Ihrer App im Dateisystem.


  2. Maximieren: DiceRoller > app > src > main > res > Drable.
  3. Ziehe alle einzelnen XML-Dateien aus dem Ordner DiceImages in Android Studio in den Ordner Drawable. Klicken Sie auf OK.
  1. Wechseln Sie zurück zur Android-Ansicht und beachten Sie, dass sich die XML-Dateien mit dem Würfelbild im Ordner für die Anzeige befinden.
  2. Klicken Sie doppelt auf dice_1.xml und sehen Sie sich den XML-Code für das Bild an. Klicken Sie auf die Schaltfläche Vorschau, um eine Vorschau davon zu sehen, wie die Vektorleiste tatsächlich aussieht.

Schritt 2: Layout aktualisieren, um Bilder zu verwenden

Jetzt, da du die Würfel-Bilddateien in deinem Ordner res/drawables hast, kannst du über das Layout und den Code deiner App darauf zugreifen. In diesem Schritt ersetzen Sie den TextView, der die Nummern anzeigt, durch einen ImageView, um die Bilder darzustellen.

  1. Öffnen Sie die Layoutdatei activity_main.xml, falls sie noch nicht geöffnet ist. Klicken Sie auf den Tab Text, um den Layout-XML-Code aufzurufen.
  2. Lösche das Element <TextView>.
  3. Fügen Sie ein <ImageView>-Element mit den folgenden Attributen hinzu:
<ImageView
   android:id="@+id/dice_image"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center_horizontal"
   android:src="@drawable/dice_1" />

Mit ImageView kannst du ein Bild in deinem Layout einblenden. Das einzige neue Attribut für dieses Element ist android:src. Damit wird die Quellressource für das Bild angegeben. In diesem Fall bedeutet eine Bildquelle von @drawable/dice_1, dass Android in den Schubressourcen (res/drawable) des Bildes dice_1 suchen sollte.

  1. Klicken Sie auf die Schaltfläche Vorschau, um sich das Layout anzusehen. Er sollte so aussehen:

Schritt 3: Code aktualisieren

  1. Öffnen Sie MainActivity. So sieht die Funktion rollDice() aus:
private fun rollDice() {
   val randomInt = Random().nextInt(6) + 1

   val resultText: TextView = findViewById(R.id.result_text)
   resultText.text = randomInt.toString()
}

Beachten Sie, dass der Verweis auf R.id.result_text rot hervorgehoben ist. Das liegt daran, dass Sie TextView aus dem Layout gelöscht haben und diese ID nicht mehr vorhanden ist.

  1. Löschen Sie die beiden Zeilen am Ende der Funktion, die die Variable resultText definieren und ihre Texteigenschaft festlegen. Du verwendest im Layout kein TextView mehr und benötigst daher keine Zeile mehr.
  2. Mit findViewByID() können Sie einen Verweis auf das neue ImageView im Layout nach ID (R.id.dice_image) abrufen und diese Ansicht einer neuen diceImage-Variable zuweisen:
val diceImage: ImageView = findViewById(R.id.dice_image)
  1. Fügen Sie einen when-Block hinzu, um ein bestimmtes Würfel-Image anhand des Werts von randomInteger auszuwählen:
val drawableResource = when (randomInt) {
   1 -> R.drawable.dice_1
   2 -> R.drawable.dice_2
   3 -> R.drawable.dice_3
   4 -> R.drawable.dice_4
   5 -> R.drawable.dice_5
   else -> R.drawable.dice_6
}

Wie bei den IDs können Sie auf die Würfelbilder im zu zeichnenden Ordner mit den Werten in der Klasse R verweisen. Dabei bezieht sich R.drawable auf den Ordner, der für die App geöffnet werden kann, und dice_1 ist eine spezifische Würfel-Ressource in diesem Ordner.

  1. Aktualisiere die Quelle von ImageView mit der Methode setImageResource() und dem Verweis auf den Würfel-Image, den du gerade gefunden hast.
diceImage.setImageResource(drawableResource)
  1. Kompilieren und führen Sie die App aus. Wenn Sie jetzt auf Roll klicken, sollte das Bild mit dem entsprechenden Bild aktualisiert werden.

Alles in deiner App funktioniert, aber es gibt noch viel mehr, als du Apps entwickeln musst. Außerdem solltest du wissen, wie du leistungsstarke Apps programmieren kannst. Das bedeutet, dass deine Apps optimal laufen sollten, selbst wenn die Nutzer nicht das teuerste Android-Gerät oder die beste Netzwerkverbindung haben. Wenn Sie weitere Funktionen hinzufügen, sollten Ihre Apps auch weiterhin problemlos funktionieren und Ihr Code sollte gut lesbar und gut organisiert sein.

In dieser Aufgabe lernst du, wie du deine App noch effizienter machen kannst.

  1. Öffnen Sie MainActivity, falls noch nicht geschehen. Achten Sie in der Methode rollDice() auf die Deklaration der Variable diceImage:
val diceImage : ImageView = findViewById(R.id.dice_image)

Da rollDice() der Klick-Handler für die Schaltfläche Roll ist, wird Ihre App jedes Mal, wenn der Nutzer auf diese Schaltfläche tippt, findViewById() aufgerufen und erhält einen weiteren Verweis auf diese ImageView. Idealerweise solltest du die Anzahl der Aufrufe für findViewById() minimieren, da das Android-System jedes Mal die gesamte Ansichtshierarchie durchsucht und das ein teurer Vorgang ist.

In einer kleinen solchen App ist es kein großes Problem. Wenn Sie eine kompliziertere App auf einem langsameren Smartphone ausführen, könnte das Aufrufen Ihrer App durch findViewById() anhalten. Stattdessen empfiehlt es sich, findViewById() einmal aufzurufen und das Objekt View in einem Feld zu speichern. Wenn der Verweis auf ImageView in einem Feld beibehalten wird, kann das System jederzeit direkt auf View zugreifen. Damit verbessert sich die Leistung.

  1. Erstellen Sie vor dem onCreate() oben im Kurs ein Feld für ImageView.
var diceImage : ImageView? = null

Im Idealfall initialisieren Sie diese Variable hier oben, wenn sie deklariert wird, oder in einem Konstruktor. Android-Aktivitäten verwenden jedoch keine Konstruktoren. Die Ansichten im Layout sind erst dann im Cache zugängliche Objekte, wenn sie durch den Aufruf von setContentView() aufgebläht werden. Du kannst die Variable diceImage überhaupt nicht initialisieren.

Eine Option besteht darin, die Variable diceImage wie in diesem Beispiel als nullbar zu definieren. Setzen Sie die Property auf null, wenn sie deklariert ist, und weisen Sie sie dann der echten ImageView in onCreate() mit findViewById() zu. Dadurch wird jedoch Ihr Code komplizierter, da Sie jetzt bei jeder Verwendung von diceImage den Wert von null prüfen müssen. Es gibt eine bessere Lösung.

  1. Ändern Sie die diceImage-Deklaration zur Verwendung des lateinit-Keywords und entfernen Sie die null-Zuweisung:
lateinit var diceImage : ImageView

Das Keyword lateinit verspricht dem Kotlin-Compiler, dass die Variable initialisiert wird, bevor der Code beliebige Vorgänge für sie aufruft. Daher müssen wir die Variable hier nicht zu null initialisieren und können sie als Variable verwenden, die nicht null ist, wenn wir sie verwenden. Es empfiehlt sich, lateinit zusammen mit Feldern zu verwenden, die Ansichten nur auf diese Weise enthalten.

  1. Nach der setContentView()-Methode verwenden Sie in onCreate() findViewById(), um ImageView zu erhalten.
diceImage = findViewById(R.id.dice_image)
  1. Löschen Sie die alte Zeile in rollDice(), die deklariert und den ImageView erhält. Sie haben diese Zeile zuvor durch die Felddeklaration ersetzt.
val diceImage : ImageView = findViewById(R.id.dice_image)
  1. Führen Sie die App noch einmal aus, um zu prüfen, ob sie weiterhin wie erwartet funktioniert.

Momentan verwendest du dice_1 als erstes Image für den Würfel. Angenommen, Sie möchten überhaupt kein Bild anzeigen, bis der Würfel zum ersten Mal gerollt wird. Es gibt verschiedene Möglichkeiten, dies zu erreichen.

  1. Öffnen Sie activity_layout.xml auf dem Tab Text.
  2. Lege im <ImageView>-Element das android:src-Attribut auf "@drawable/empty_dice" fest:
android:src="@drawable/empty_dice" 

Das Bild empty_dice war eines der Bilder, die du heruntergeladen und dem Ordner drawable hinzugefügt hast. Es ist genau so groß wie die anderen Würfelbilder, nur das Feld ist leer. Dieses Bild wird beim Start der App angezeigt.

  1. Klicken Sie auf den Tab Design. Das Würfelbild ist jetzt leer, ist aber auch in der Vorschau nicht sichtbar.



    Es ist ziemlich häufig, dass die Inhalte eines Designs während der Laufzeit dynamisch definiert werden. Beispielsweise sollte jede App, die Daten aus dem Internet abruft, mit einem leeren oder leeren Bildschirm beginnen. Aber es ist hilfreich, wenn du eine App so gestaltest, dass sie Platzhalterdaten im Layout enthält, damit du wissen kannst, was genau dargestellt wird.
  2. Kopieren Sie in activity_layout.xml die android:src-Zeile und fügen Sie eine zweite Kopie ein. Ändern Sie das Wort „Android“ in „&tools“. Ihre beiden Attribute sehen dann so aus:
android:src="@drawable/empty_dice" 
tools:src="@drawable/empty_dice" />

Hier haben Sie den XML-Namespace dieses Attributs vom Standard-Namespace android zum Namespace tools geändert. Der Namespace tools wird verwendet, wenn du Platzhalterinhalte definieren möchtest, die nur in der Vorschau oder im Designeditor in Android Studio verwendet werden. Attribute mit dem Namespace tools werden beim Kompilieren der App entfernt.

Namespaces werden verwendet, um Mehrdeutigkeiten in Bezug auf Attribute zu vermeiden, die denselben Namen haben. Beispielsweise haben beide Attribute im <ImageView>-Tag denselben Namen (src), der Namespace ist jedoch anders.

  1. Prüfen Sie das <LinearLayout>-Element im Stammverzeichnis der Layoutdatei. Sie sehen dann die beiden hier definierten Namespaces.
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   ...
  1. Ändern Sie das tools:src-Attribut im ImageView-Tag in dice_1 anstelle von empty_dice:
android:src="@drawable/empty_dice" 
tools:src="@drawable/dice_1" />

Hinweis: Das dice_1-Bild dient jetzt als Platzhalterbild in der Vorschau.

  1. Kompilieren und führen Sie die App aus. Beachten Sie, dass das Würfelbild in der tatsächlichen App leer ist, bis Sie auf Roll klicken oder tippen.

Einer der großen Vorteile für Android-Entwickler ist die große Menge an Geräten, auf denen ihr Code ausführen kann – vom Nexus One bis zum Pixel, über Formfaktoren wie Tablets, Pixelbooks, Smartwatches, Fernseher und Autos.

Wenn du für Android schreibst, musst du für jedes dieser Geräte keine vollständig separaten Apps schreiben – auch solche, die auf völlig unterschiedlichen Formfaktoren wie Uhren oder Fernsehgeräten laufen. Es gibt jedoch Einschränkungen und Kompatibilitätsstrategien, die alle diese Aspekte berücksichtigen müssen.

In dieser Aufgabe erfahren Sie, wie Sie Ihre App auf bestimmte Android API-Levels (Versionen) ausrichten und die Android Jetpack-Bibliotheken zur Unterstützung älterer Geräte verwenden können.

Schritt 1: API-Levels kennenlernen

Im vorherigen Codelab haben Sie beim Erstellen Ihres Projekts angegeben, welches Android API-Level Ihre App unterstützen soll. Das Android-Betriebssystem hat verschiedene Versionsnummern, die nach leckeren Leckereien benannt sind. Jede Version des Betriebssystems bietet neue Funktionen. Beispielsweise wurde Android Oreo mit Unterstützung für Bild im Bild-Apps geliefert, während Android Pie Slices eingeführt hat. Die API-Levels entsprechen den Android-Versionen. Beispiel: API 19 entspricht Android 4.4 (KitKat).

Verschiedene Faktoren haben Einfluss darauf, inwieweit die Hardware unterstützt wird, ob die Nutzer ihre Geräte aktualisieren oder ob die Hersteller unterschiedliche Betriebssystemstufen unterstützen.

Beim Erstellen deines App-Projekts gibst du an, welche API-Ebene deine App mindestens unterstützt. Das heißt, Sie geben die älteste Android-Version an, die Ihre App unterstützt. Ihre App hat außerdem eine Ebene, auf der sie kompiliert wird, und eine Ebene, auf die sie ausgerichtet ist. Jede dieser Ebenen ist ein Konfigurationsparameter in Ihren Gradle-Build-Dateien.

  1. Maximieren Sie den Ordner Gradle Scripts und öffnen Sie die Datei build.gradle (Module: app).

    In dieser Datei sind Build-Parameter und Abhängigkeiten für das Anwendungsmodul definiert. In der Datei build.gradle (Projekt: DiceRoller) werden Build-Parameter für das gesamte Projekt definiert. In vielen Fällen ist Ihr App-Modul das einzige Modul in Ihrem Projekt. Diese Abteilung kann daher beliebig erscheinen. Wenn Ihre App jedoch komplexer wird und Sie sie in mehrere Teile aufteilen oder Ihre App Plattformen wie Android Watch unterstützt, sehen Sie unter Umständen mehrere Module im selben Projekt.
  2. Prüfe den Abschnitt android oben in der Datei build.gradle. (Das folgende Beispiel ist nicht der gesamte Abschnitt. Er enthält aber das, was Sie am meisten mit diesem Codelab interessiert.)
android {
   compileSdkVersion 28
   defaultConfig {
       applicationId "com.example.android.diceroller"
       minSdkVersion 19
       targetSdkVersion 28
       versionCode 1
       versionName "1.0"
   }
  1. Prüfe den Parameter compileSdkVersion.
compileSdkVersion 28

Dieser Parameter gibt die Android API-Level an, die Gradle verwenden soll, um deine App zu kompilieren. Das ist die neueste Android-Version, die deine App unterstützt. Das bedeutet, dass deine Anwendung die API-Funktionen dieser API-Ebene und niedriger verwenden kann. In diesem Fall unterstützt Ihre App API 28, die Android 9 (Pie) entspricht.

  1. Prüfe den Parameter targetSdkVersion, der sich im Abschnitt defaultConfig befindet:
targetSdkVersion 28

Dieser Wert ist die aktuelle API, mit der Sie Ihre App getestet haben. In vielen Fällen ist dies der gleiche Wert wie compileSdkVersion.

  1. Prüfe den Parameter minSdkVersion.
minSdkVersion 19

Dieser Parameter ist der wichtigste von drei, da er die älteste Version von Android bestimmt, auf der Ihre App ausgeführt wird. Auf Geräten mit Android OS, die älter als diese API-Ebene sind, kann Ihre App überhaupt nicht ausgeführt werden.

Es kann eine Herausforderung sein, das Mindest-API-Level für Ihre App auszuwählen. Wenn Sie das API-Level zu niedrig festlegen, erhalten Sie keine neuen Funktionen in Android. Wenn Sie sie zu hoch anstellen, wird Ihre App möglicherweise nur auf neueren Geräten ausgeführt.

Klicken Sie bei der Einrichtung Ihres Projekts zu der Stelle, an der Sie die API-Mindestebene für Ihre App festlegen, und klicken Sie auf Unterstützung bei der Auswahl, um das Dialogfeld API-Versionsverteilung aufzurufen. Das Dialogfeld enthält Informationen darüber, wie viele Geräte unterschiedliche Betriebssystemstufen verwenden, und welche Funktionen hinzugefügt oder geändert wurden. Weitere Informationen zu den Auswirkungen der Unterstützung auf verschiedene API-Levels finden Sie auch in den Versionshinweisen zur Android-Dokumentation und im Dashboard.

Schritt 2: Kompatibilität prüfen

Das Schreiben verschiedener Android API-Levels ist eine häufige Herausforderung für Entwickler von Apps. Deshalb hat das Android-Framework-Team bereits viel Arbeit geleistet.

2011 veröffentlichte das Team die erste Supportbibliothek. Das ist eine von Google entwickelte Bibliothek, die abwärtskompatible Kurse und nützliche Funktionen bietet. 2018 hat Google Android Jetpack angekündigt, eine Sammlung von Bibliotheken, die viele der vorherigen Klassen und Funktionen der Supportbibliothek umfasst und gleichzeitig um die Supportbibliothek erweitert wird.

  1. Öffnen Sie MainActivity.
  2. Beachten Sie, dass Ihre MainActivity-Klasse nicht von Activity selbst, sondern von AppCompatActivity geht.
class MainActivity : AppCompatActivity() { 
...

AppCompatActivity ist eine Kompatibilitätsklasse, bei der sichergestellt wird, dass Ihre Aktivitäten auf verschiedenen Plattformen gleich sind.

  1. Klicken Sie neben der Zeile mit import auf das +-Symbol, um die Importe für Ihren Kurs zu maximieren. Die Klasse AppCompatActivity wird aus dem androidx.appcompat.app-Paket importiert. Der Namespace für die Android Jetpack-Bibliotheken ist androidx.
  2. Öffnen Sie build.gradle (Modul: App) und scrollen Sie nach unten zum Bereich „Abhängigkeiten“.
dependencies {
   implementation fileTree(dir: 'libs', include: ['*.jar'])
   implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
   implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
   implementation 'androidx.core:core-ktx:1.0.1'
   implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
   testImplementation 'junit:junit:4.12'
   androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
   androidTestImplementation 
        'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}

Beachten Sie die Abhängigkeit von der appcompat-Bibliothek, die Teil von androidx ist und die Klasse AppCompatActivity enthält.

Schritt 3: Kompatibilität für Vektor-Dables hinzufügen

Du nutzt deine neuen Kenntnisse über Namespaces, Gradle und Kompatibilität, um eine letzte Anpassung an deiner App vorzunehmen, mit der deine App-Größe auf älteren Plattformen optimiert wird.

  1. Maximieren Sie den Ordner res und maximieren Sie dann Drawable. Klicken Sie doppelt auf die Würfelbilder.

    Wie Sie bereits erfahren haben, sind alle Würfelbilder XML-Dateien, die die Farben und Formen des Würfels definieren. Diese Art von Dateien wird als Vektor-Dableable bezeichnet. Das Tolle an Vektor-Darstellern im Vergleich zu Bitmapbildformaten wie PNG ist, dass Vektor-Dableables problemlos skalieren können, ohne dabei die Qualität zu beeinträchtigen. Außerdem ist eine Vektor-Dramed normalerweise eine wesentlich kleinere Datei als dasselbe Bild in einem Bitmapformat.

    Beachte bitte, dass sie ab API 21 unterstützt werden kann. Das Mindest-SDK Ihrer App ist jedoch auf API 19 festgelegt. Wenn Sie Ihre App auf einem API 19-Gerät oder -Emulator ausprobiert haben, sehen Sie, dass die App ordnungsgemäß erstellt und ordnungsgemäß ausgeführt wird. Wie funktioniert das?

    Wenn du deine App erstellst, wird im Gradle-Build-Prozess von jeder Vektordatei eine PNG-Datei generiert. Diese PNG-Dateien werden auf allen Android-Geräten unter einer Version unter 21 verwendet. Durch diese zusätzlichen PNG-Dateien wird die Größe deiner App vergrößert. Sie sind unnötig unnötig, da sie die Downloads der Nutzer verlangsamen und mehr Geräte beanspruchen. Außerdem ist die Wahrscheinlichkeit größer, dass große Apps deinstalliert werden und dass Nutzer ihre Apps nicht herunterladen oder abbrechen können.

    Gut zu finden ist die Android X-Kompatibilitätsbibliothek für Vektor-Drawables bis auf API-Level 7.
  2. Öffnen Sie build.gradle (Modul: App). Fügen Sie diese Zeile zum Abschnitt defaultConfig hinzu:
vectorDrawables.useSupportLibrary = true
  1. Klicken Sie auf die Schaltfläche Jetzt synchronisieren. Bei jeder Änderung einer build.gradle-Datei müssen Sie die Build-Dateien mit dem Projekt synchronisieren.
  2. Öffne die main_activity.xml-Layoutdatei. Füge diesen Namespace dem Stamm-<LinearLayout>-Tag unter dem tools-Namespace hinzu:
xmlns:app="http://schemas.android.com/apk/res-auto"

Der Namespace app bezieht sich auf Attribute, die entweder aus Ihrem benutzerdefinierten Code oder aus Bibliotheken stammen und nicht aus dem zentralen Android-Framework.

  1. Ändern Sie das android:src-Attribut im <ImageView>-Element in app:srcCompat.
app:srcCompat="@drawable/empty_dice"


Das Attribut app:srcCompat verwendet die Android X-Bibliothek, um Vektor-Drawables in älteren Android-Versionen bis API-Level 7 zu unterstützen.

  1. Erstelle und führe deine App aus. Auf dem Bildschirm siehst du nichts anders, nur dass deine App jetzt keine PNG-Dateien mehr für die Würfelbilder verwendet – unabhängig davon, wo sie ausgeführt werden, was eine kleinere App-Datei bedeutet.

Android Studio-Projekt: DiceRollerFinal

Herausforderung: Ändern Sie die DiceRoller App auf zwei Würfel. Wenn der Nutzer auf die Schaltfläche Rollieren tippt, sollte der Wert für den Würfel unabhängig vom Wert sein.

Tipp: Erstellen Sie eine neue private Funktion, um ein zufälliges Zeichen für das Bild zu erhalten und geben Sie eine Ganzzahl für die Zeichenressource zurück. Verwenden Sie diese Funktion für jedes der Würfelbilder.

private fun getRandomDiceImage() : Int { ... }

Code für die Codierung von Lösungen

Android Studio-Projekt: DiceRollerFinal-challenge

App-Ressourcen:

  • Die Ressourcen Ihrer App können Bilder und Symbole, Standardfarben in der App, Strings und XML-Layouts enthalten. Alle diese Ressourcen werden im Ordner res gespeichert.
  • Im Ordner drawable-Ressourcen sollten Sie alle Image-Ressourcen für Ihre Anwendung ablegen.

So verwenden Sie Vektorzeichenfelder in Bildansichten:

  • Vektor-Zeichnen sind Bilder im XML-Format. Vektor-Dableables sind flexibler als Bitmapbilder (z. B. PNG-Dateien), da sie an jede Größe und Auflösung angepasst werden können.
  • Verwenden Sie ein <ImageView>-Element, um einem Layout eine App hinzuzufügen. Die Quelle des Bildes liegt im Attribut android:src. Wenn Sie auf den Ordner mit zeichnenden Ressourcen verweisen möchten, verwenden Sie @drawable, z. B. "@drawable/image_name".
  • Verwenden Sie die Ansicht ImageView im Code von MainActivity für das Bild. Du kannst setImageResource() verwenden, um das Bild der Ansicht in eine andere Ressource zu ändern. Mit R.drawable kannst du auf bestimmte Zeichnungen verweisen, z. B. setImageResource(R.drawable.image_name).

Das Keyword lateinit:

  • Minimieren Sie die Aufrufe von findViewById() in Ihrem Code, indem Sie Felder deklarieren, die diese Ansichten enthalten, und die Felder in onCreate() initialisieren. Verwenden Sie das Keyword lateinit für das Feld, damit es nicht als ungültig erklärt werden kann.

Der Namespace tools für Designzeit-Attribute:

  • Verwenden Sie das tools:src-Attribut im <ImageView>-Element Ihres Layouts, um ein Bild nur in der Vorschau oder im Designeditor von Android Studio anzuzeigen. Anschließend kannst du für die finale App ein leeres Bild für android:src verwenden.
  • Verwende den Namespace tools in der Android-Layoutdatei, um in Android Studio Platzhalterinhalte oder Hinweise für das Layout zu erstellen. Von den tools-Attributen deklarierte Daten werden in der endgültigen App nicht verwendet.

API-Ebenen:

  • Jedes Android-Betriebssystem hat eine offizielle Versionsnummer und einen offiziellen Namen (z. B. Android 9.0 und Pit) sowie ein API-Level (API 28). Mithilfe der API-Levels in den Gradle-Dateien deiner App kannst du angeben, welche Android-Versionen von deiner App unterstützt werden.
  • Der Parameter compileSdkVersion in der Datei build.gradle gibt die Android API-Ebene an, die Gradle verwenden soll, um Ihre App zu kompilieren.
  • Der Parameter targetSdkVersion gibt das neueste API-Level an, mit dem du deine App getestet hast. In vielen Fällen hat dieser Parameter denselben Wert wie compileSdkVersion.
  • Der Parameter minSdkVersion gibt die älteste API-Ebene an, auf der deine App ausgeführt werden kann.

Android-Jetpack:

  • Android Jetpack ist eine von Google entwickelte Mediathek mit Abwärtskompatibilität und hilfreichen Funktionen für ältere Android-Versionen. Jetpack ersetzt und erweitert die Bibliothek, die früher als die Android Support Library bezeichnet wurde.
  • Aus dem androidx-Paket importierte Klassen beziehen sich auf die Jetpack-Bibliotheken. Abhängigkeiten von Jetpack in Ihrer build.gradle-Datei beginnen auch mit androidx.

Abwärtskompatibilität für Vektor-Dableables:

  • Vektor-Dableables werden nur in Android-Versionen ab API 21 nativ unterstützt. In älteren Versionen werden von Gradle PNG-Dateien für die Zeichnungen erstellt, wenn Ihre App erstellt wird.
  • Mit dem Konfigurationsparameter vectorDrawables.useSupportLibrary = true in der Datei build.gradle kannst du festlegen, dass die Android Support Library für Vektor-Dableables in älteren API-Versionen verwendet werden soll.
  • Sobald du die Supportbibliothek für Vektor-Drawables aktiviert hast, verwende das Attribut app:srcCompat im Element <ImageView> anstelle von android:src, um die Quelle der Vektor-Dachbarkeit für dieses Bild anzugeben.

Der Namespace app:

  • Der Namespace app in Ihrer XML-Layoutdatei bezieht sich auf Attribute, die entweder aus Ihrem benutzerdefinierten Code oder aus Bibliotheken stammen und nicht aus dem Android-Hauptframework.

Udacity-Kurs:

Android-Entwicklerdokumentation:

Sonstiges:

In diesem Abschnitt werden mögliche Hausaufgaben für Schüler oder Studenten aufgeführt, die an diesem von einem Kursleiter geleiteten Codelab arbeiten. Die Lehrkraft kann Folgendes tun:

  • Bei Bedarf können Sie die entsprechenden Aufgaben zuweisen.
  • Schülern mitteilen, wie sie Aufgaben für die Aufgabe abgeben
  • Benoten Sie die Hausaufgaben.

Lehrkräfte können diese Vorschläge so oft oder so oft verwenden, wie sie möchten. anderen Aufgaben können sie nach Belieben zugewiesen werden.

Wenn Sie alleine an diesem Codelab arbeiten, können Sie Ihr Wissen mit diesen Hausaufgaben testen.

Eine App ändern

Füge der DiceRoller App eine Schaltfläche Löschen hinzu, durch die das Würfelbild auf das leere Bild zurückgesetzt wird.

Diese Fragen beantworten

Frage 1

Welches <ImageView>-Attribut gibt ein Quellbild an, das nur in Android Studio verwendet werden sollte?

  • android:srcCompat
  • app:src
  • tools:src
  • tools:sourceImage

Frage 2

Mit welcher Methode wird die Image-Ressource für eine ImageView im Kotlin-Code geändert? xmx

  • setImageResource()
  • setImageURI()
  • setImage()
  • setImageRes()

Frage 3

Was bedeutet das lateinit-Keyword in einer Variablendeklaration im Kotlin-Code?

  • Die Variable wird nie initialisiert.
  • Die Variable wird nur während der App-Laufzeit initialisiert.
  • Die Variable wird automatisch in null initialisiert.
  • Die Variable wird später initialisiert. Das versprechen ich.

Frage 4

Welche Gradle-Konfiguration gibt das neueste API-Level an, mit dem Ihre App getestet wurde?

  • minSdkVersion
  • compileSdkVersion
  • targetSdkVersion
  • testSdkVersion

Frage 5

Im Code erscheint eine Importzeile, die mit androidx beginnt. What does this mean?

  • Die Klasse ist Teil der Android Jetpack-Bibliotheken.
  • Die Klasse befindet sich in einer externen Bibliothek, die beim Laden der App dynamisch geladen wird.
  • Die Klasse ist &trat; und ist optional.
  • Die Klasse gehört zur XML-Unterstützung von Android.

App zur Benotung einreichen

Prüfen Sie, ob die App die folgenden Anforderungen erfüllt:

  • Das App-Layout sollte eine Bildansicht und zwei Schaltflächen enthalten.
  • Der App-Code sollte zwei Klick-Handler festlegen, einen für jede Schaltfläche.
  • Wenn der Klick-Handler für die Schaltfläche Löschen verwendet wird, muss das Würfelbild auf R.drawable.empty_dice gesetzt sein.

Mit der nächsten Lektion beginnen: 1.4: Selbsthilfe-Tools

Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage zu Kotlin-Grundlagen für Android.