Erstellen einer Material Design-Benutzeroberfläche mit Registerkarten in einer Android-App
German (Deutsch) translation by Władysław Łucyszyn (you can also view the original English article)



Das Materialdesign-Team von Google definiert die Funktionalität von Tabs in Android einfach wie folgt:
Registerkarten erleichtern das Erkunden und Wechseln zwischen verschiedenen Ansichten.
In diesem Beitrag erfahren Sie, wie Sie Registerkarten mit der TabLayout- und ViewPager-API anzeigen. In diesem praktischen Tutorial behandeln wir Folgendes:
- Die Komponenten
TabLayoutundViewPager. - Die verschiedenen Tab-Modi: scrollbar und fest.
- So zeigen Sie Symbole anstelle von Text für die Registerkartentitel an.
- Als Bonus erfahren Sie auch, wie Sie die Android Studio-Vorlagenfunktion verwenden, um Ihr Projekt schnell mit einer Benutzeroberfläche mit Registerkarten zu booten.
Ein Beispielprojekt für dieses Tutorial finden Sie in unserem GitHub-Repository, damit Sie es leicht verfolgen können.
Voraussetzungen
Um diesem Tutorial folgen zu können, benötigen Sie:
- Android Studio 3.0 oder höher
- Kotlin-Plugin 1.1.51 oder höher
Sie können auch alle Vor- und Nachteile der Kotlin-Sprache in meiner Kotlin von Grund auf neu-Reihe lernen.


KotlinKotlin From Scratch: Nullbarkeit, Schleifen und BedingungenChike Mgbemena

KotlinKotlin von Grund auf: Klassen und ObjekteChike Mgbemena
Einführung in die TabLayout-Komponente
Laut der offiziellen Android-Dokumentation zu TabLayout heißt es:
TabLayout
bietet ein horizontales Layout zum Anzeigen von Registerkarten.
Die TabLayout-Komponente ist eine der Komponenten, die als Teil der Materialdesign-Artefakte eingeführt wurden. Darüber hinaus ist es auch in der Design Support Library enthalten. Wenn in einem TabLayout eine Registerkarte ausgewählt oder angetippt wird, wird dem Benutzer eine andere Seite (oder ein anderes Fragment) angezeigt.
Die TabLayout-Komponente kann die Anzeige von Registerkarten auf zwei Arten haben: fest und scrollbar. Wenn die Registerkarten fixiert sind, werden alle Registerkarten gleichzeitig auf dem Bildschirm angezeigt.
Der Screenshot unten ist die neueste offizielle WhatsApp Android-App (zum Zeitpunkt dieses Schreibens), die ein TabLayout mit einer festen Moduskonfiguration verwendet.


Wenn in scrollbaren Registerkarten die Anzahl der Registerkarten für den Bildschirm zu groß wird, kann der Benutzer nach links oder rechts streichen, um weitere Registerkarten anzuzeigen.
Hier ist ein Beispiel für ein TabLayout mit scrollbarem Tab-Modus, das in der neuesten Version der News & Weather Android-App von Google vorgestellt wird.


Darüber hinaus können die auf einer Registerkarte angezeigten Informationen Text, ein Symbol oder eine Kombination aus Text und Symbol sein. Die neueste Twitter-App für Android verwendet beispielsweise auf jeder Registerkarte Symbole anstelle von Text.


In den folgenden Abschnitten werden wir uns mit der Codierung einer einfachen App befassen, die TabLayout mit einem ViewPager verwendet. Lassen Sie uns ins Rollen kommen!
Design ist nicht nur das, wie es aussieht und sich anfühlt. Design ist, wie es funktioniert. - Steve Jobs
1. Erstellen Sie ein Android Studio-Projekt
Starten Sie Android Studio 3 und erstellen Sie ein neues Projekt (Sie können es TabLayoutDemo nennen) mit einer leeren Aktivität namens MainActivity.


2. Erstellen der Fragmente (Seiten)
Wir werden ein TabLayout mit nur drei Registerkarten erstellen. Wenn jede der Registerkarten ausgewählt ist, wird ein anderes Android-Fragment oder eine andere Seite angezeigt. Lassen Sie uns nun die drei Android-Fragmente für jede der Registerkarten erstellen. Wir beginnen mit der ersten Fragmentklasse, und Sie sollten für die verbleibenden zwei Fragmentklassen – FragmentTwo.kt und FragmentThree.kt – ähnlich vorgehen.
Hier ist mein FragmentOne.kt:
1 |
import android.os.Bundle import android.support.v4.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup class FragmentOne : Fragment() { override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater!!.inflate(R.layout.fragment_one, container, false) companion object { fun newInstance(): FragmentOne = FragmentOne() } } |
2 |
Hier ist auch mein R.layout.fragment_one:
1 |
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="FragmentOne" android:gravity="center_vertical|center_horizontal"/> </LinearLayout> |
2 |
3. Hinzufügen von TabLayout und ViewPager
Um TabLayout und ViewPager in Ihrem Projekt zu verwenden, stellen Sie sicher, dass Sie die Designunterstützung und auch das Android-Unterstützungsartefakt importieren. Fügen Sie diese also der Datei build.gradle Ihres Moduls hinzu, um sie zu importieren.
1 |
dependencies { implementation 'com.android.support:design:26.1.0' implementation 'com.android.support:support-v4:26.1.0' } |
2 |
Besuchen Sie auch Ihre Datei res/layout/activlty_main.xml, um sowohl das TabLayout-Widget als auch die ViewPager-Ansicht einzuschließen.
1 |
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:contentInsetStartWithNavigation="0dp" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay"/> <android.support.design.widget.TabLayout android:id="@+id/tab_layout" style="@style/CustomTabLayout" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_gravity="left" android:background="@color/colorPrimary" app:tabGravity="fill" app:tabMode="fixed"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.design.widget.CoordinatorLayout> |
2 |
Hier haben wir ein einfaches TabLayout mit der ID tab_layout erstellt. In unserem TabLayout-XML-Widget können Sie sehen, dass wir einige Attribute eingefügt haben – wie zum Beispiel app:tabMode zum fixed und auch app:tabGravity zum fill. Die Eigenschaft app:tabGravity wird verwendet, um zu konfigurieren, wie die Registerkartenelemente angezeigt werden, um den verfügbaren Platz einzunehmen. Wir setzen dies auf fill, wodurch die Elemente gleichmäßig über die Breite des TabLayout verteilt werden. Beachten Sie, dass dies auf breiteren Displays wie Tablets besser sichtbar ist.
Ich habe auch ein benutzerdefiniertes Stilattribut (@style/CustomTabLayout) in unser TabLayout-Widget eingefügt.
1 |
<style name="CustomTabLayout" parent="Widget.Design.TabLayout"> <item name="tabIndicatorColor">@android:color/white</item> <item name="tabIndicatorHeight">3dp</item> <item name="tabBackground">?attr/selectableItemBackground</item> <item name="tabTextAppearance">@style/CustomTabTextAppearance</item> <item name="tabSelectedTextColor">@android:color/white</item> </style> |
2 |
Wir beginnen mit dem Anpassen unseres TabLayout, indem wir die Werte der Attribute festlegen, die auf das TabLayout angewendet werden sollen. Hier sind die Details für einige der angewendeten Attribute:
-
tabIndicatorColor: Legt die Farbe des Tab-Indikators für den aktuell ausgewählten Tab fest. Dies kann auch programmgesteuert festgelegt werden, indemsetSelectedTabIndicatorColor()für eineTabLayout-Instanz aufgerufen wird. -
tabIndicatorHeight: Legt die Höhe des Tab-Indikators für den aktuell ausgewählten Tab fest. Dies kann auch programmgesteuert festgelegt werden, indemsetSelectedTabIndicatorHeight()auf einerTabLayout-Instanz aufgerufen wird. -
tabSelectedTextColor: legt die Textfarben für die verschiedenen Zustände (normal, ausgewählt) fest, die für die Registerkarten verwendet werden. Das Äquivalent dieses Attributs in Java istsetTabTextColors().
Unmittelbar nach dem Erstellen unseres TabLayout-Widgets in XML war die nächste Ansicht ein ViewPager. Die offizielle Dokumentation sagt folgendes über ViewPager:
Layout-Manager, der es dem Benutzer ermöglicht, nach links und rechts durch die Datenseiten zu blättern...
4. Erstellen des PagerAdapters
Wir müssen eine Unterklasse in SampleAdapter.kt erstellen, die den FragmentPagerAdapter erweitert. Diese Klasse ist für die Verwaltung der verschiedenen Fragmente verantwortlich, die auf den Registerkarten angezeigt werden.
1 |
import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentPagerAdapter class SampleAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { override fun getItem(position: Int): Fragment? = when (position) { 0 -> FragmentOne.newInstance() 1 -> FragmentTwo.newInstance() 2 -> FragmentThree.newInstance() else -> null } override fun getPageTitle(position: Int): CharSequence = when (position) { 0 -> "Tab 1 Item" 1 -> "Tab 2 Item" 2 -> "Tab 3 Item" else -> "" } override fun getCount(): Int = 3 } |
2 |
Hier überschreiben wir drei Methoden der Elternklasse: getItem(), getCount() und getPageTitle(). Hier die Erklärungen zu den Methoden:
-
getItem(): gibt einFragmentfür eine bestimmte Position innerhalb desViewPagerszurück. -
getCount(): gibt an, wie viele Seiten sich imViewPagerbefinden werden. -
getPageTitle(): Diese Methode wird vomViewPageraufgerufen, um eine Titelzeichenfolge zur Beschreibung des angegebenen Tabs zu erhalten.
Wenn die ausgewählte Registerkarte beispielsweise die erste Registerkarte mit dem Titel "Tab 1 Item" ist, wird dem Benutzer sofort eine FragmentOne-Seite angezeigt.
5. Initialisierung von Komponenten
Als Nächstes initialisieren wir Instanzen von TabLayout, ViewPager und SampleAdapter. Die Initialisierung erfolgt in onCreate() in MainActivity.kt.
1 |
import android.os.Bundle import android.support.design.widget.TabLayout import android.support.v4.view.ViewPager import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initToolbar() val tabLayout: TabLayout = findViewById(R.id.tab_layout) val viewPager: ViewPager = findViewById(R.id.view_pager) val adapter = SampleAdapter(supportFragmentManager) viewPager.adapter = adapter tabLayout.setupWithViewPager(viewPager) tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab) { } override fun onTabUnselected(tab: TabLayout.Tab) { } override fun onTabReselected(tab: TabLayout.Tab) { } }) } private fun initToolbar() { val toolbar: Toolbar = findViewById(R.id.toolbar) setSupportActionBar(toolbar) supportActionBar!!.title = "TabLayout Demo" } } |
2 |
Wir haben Referenzen zu unserem TabLayout und ViewPager von R.layout.activity_main erhalten und diese initialisiert. Wir haben auch eine Instanz unseres SampleAdapters erstellt und dabei eine Instanz von FragmentManager als Argument übergeben. Wir müssen die Ansichten für unseren ViewPager bereitstellen, also haben wir setAdapter() aufgerufen und unseren erstellten Adapter an ihn übergeben. Schließlich haben wir setupWithViewPager() auf einer Instanz von TabLayout aufgerufen, um etwas Arbeit zu erledigen:
- Erstellung des benötigten Reiters für jede Seite
- Einrichten der erforderlichen Listener
Wenn der Benutzer auf eine Registerkarte tippt, ändert er die Seiten im ViewPager und zeigt die erforderliche Seite (oder das Fragment) an. Außerdem aktualisiert das Wischen zwischen den Seiten die ausgewählte Registerkarte. Mit anderen Worten, diese Methode hilft uns, die Änderung des Bildlaufstatus und das Klicken auf die Registerkarten zu berücksichtigen.
Der onTabSelectedListener() wird verwendet, um einen Listener einzuschließen, der aufgerufen wird, wenn sich die Tabulatorauswahl ändert. Wir haben die folgenden Rückrufe überschrieben:
-
onTabSelected(): wird ausgelöst, wenn ein Tab in den ausgewählten Zustand eintritt. -
onTabUnselected(): wird aufgerufen, wenn eine Registerkarte den ausgewählten Zustand verlässt. -
onTabReselected(): Wird aufgerufen, wenn ein bereits ausgewählter Tab vom Benutzer erneut ausgewählt wird.
Beachten Sie, dass wir den Tab-Modus auch programmgesteuert – statt über die Layout-XML – mit setTabMode() auf einer Instanz von TabLayout festlegen können. Wir übergeben dieser Methode den Modus (fest oder scrollbar) als Argumente. Beispielsweise können wir TabLayout.MODE_FIXED für einen festen Modus übergeben – oder TabLayout.MODE_SCROLLABLE für einen scrollbaren Modus.
1 |
tabLayout.tabMode = TabLayout.MODE_FIXED tabLayout.tabMode = TabLayout.MODE_SCROLLABLE |
2 |
Beachten Sie, dass Sie, wenn Sie die Registerkarten explizit erstellen möchten, anstatt die Hilfsmethode setUpWithViewPager() zu verwenden, stattdessen newTab() für eine TabLayout-Instanz verwenden können.
1 |
val tabLayout: TabLayout = findViewById(R.id.tab_layout) tabLayout.addTab(tabLayout.newTab().setText("Songs")) tabLayout.addTab(tabLayout.newTab().setText("Albums")) tabLayout.addTab(tabLayout.newTab().setText("Artists")) |
2 |
Beachten Sie auch, dass wir die Registerkarten explizit über XML statt programmgesteuert erstellen könnten.
1 |
<android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.design.widget.TabItem android:id="@+id/tabItem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Songs"/> <android.support.design.widget.TabItem android:id="@+id/tabItem2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Albums"/> <android.support.design.widget.TabItem android:id="@+id/tabItem3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Artists"/> </android.support.design.widget.TabLayout> |
2 |
6. Testen der App
Endlich können Sie die App ausführen!


Versuchen Sie, mit der Anwendung zu interagieren, indem Sie nach links oder rechts wischen und auf die Registerkarten tippen.
7. Scrollbare Registerkarten
In den offiziellen Richtlinien zum Materialdesign auf Registerkarten heißt es zu scrollbaren Registerkarten:
Bildlaufbare Registerkarten zeigen zu jedem Zeitpunkt eine Teilmenge der Registerkarten an. Sie können längere Registerkartenbeschriftungen und eine größere Anzahl von Registerkarten enthalten als feste Registerkarten. Scrollbare Registerkarten werden am besten zum Durchsuchen von Kontexten in Touch-Oberflächen verwendet, wenn Benutzer die Registerkartenbeschriftungen nicht direkt vergleichen müssen.
Sehen wir uns an, wie Sie Registerkarten mit der Konfiguration des scrollbaren Modus erstellen. Ich habe den Titel für jede der Registerkarten länger als zuvor gemacht. Hier ist das Ergebnis im festen Modus:


Sie können sehen, dass TabLayout mehrere Zeilen verwendet hat, um jeden Titel der Registerkarte anzuzeigen. In einigen Situationen werden sogar die Titel abgeschnitten! Dies führt zu einer schlechten Benutzererfahrung. Wenn Ihre Tab-Titel sehr lang sein müssen, sollten Sie den scrollbaren Modus in Betracht ziehen. Beachten Sie auch, dass es empfohlen wird, den Tab-Modus scrollbar zu machen, wenn Sie mehr als vier Registerkarten haben.
Lassen Sie uns die app:tabMode-Eigenschaft von fixed in scrollable.
1 |
<android.support.design.widget.TabLayout <!-- ... --> app:tabMode="scrollable"/> |
2 |
Denken Sie daran, dass Sie den Tab-Modus auch programmgesteuert einstellen können, wie bereits erwähnt.


8. Registerkartensymbole anzeigen
Sehen wir uns nun an, wie Sie stattdessen den Text des Registerkartenelements durch Symbole ersetzen.
1 |
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // ... tabLayout.setupWithViewPager(viewPager) tabLayout.getTabAt(0)!!.setIcon(android.R.drawable.ic_dialog_email) tabLayout.getTabAt(1)!!.setIcon(android.R.drawable.ic_dialog_info) tabLayout.getTabAt(2)!!.setIcon(android.R.drawable.ic_dialog_alert) // ... } // ... } |
2 |
Hier haben wir getTabAt() für eine Instanz von TabLayout aufgerufen. Der Aufruf dieser Methode gibt die Registerkarte am angegebenen Index zurück. Als nächstes rufen wir setIcon() auf. Durch Aufrufen dieser Methode wird das auf dieser Registerkarte angezeigte Symbol festgelegt.
Ich habe auch den Tab-Modus fest eingestellt.
1 |
<android.support.design.widget.TabLayout app:tabMode="fixed"/> |
2 |
Ich überschreibe immer noch getPageTitle() im SampleAdapter.
1 |
class SampleAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { // ... override fun getPageTitle(position: Int): CharSequence = when (position) { 0 -> "TAB 1" 1 -> "TAB 2" 2 -> "TAB 3" else -> "" } // ... } |
2 |
Hier ist das Ergebnis:


Wenn Sie jetzt nur die Symbole haben möchten, überschreiben Sie getPageTitle() einfach nicht.


9. Bonus: Verwenden von Android Studio-Vorlagen
Anstatt so viel Code zu schreiben, nur um eine Oberfläche oder Aktivität mit Registerkarten von Grund auf neu zu erstellen, verfügt Android Studio 3.0 über einige bereits vorhandene Codevorlagen (verfügbar in Java und Kotlin), mit denen Sie Ihr Projekt starten können. Eine solche Vorlage kann zum Erstellen einer Aktivität mit Registerkarten verwendet werden.
Ich zeige Ihnen, wie Sie diese praktische Funktion in Android Studio 3 verwenden.
Starten Sie für ein neues Projekt Android Studio 3.


Geben Sie den Anwendungsnamen ein und klicken Sie auf die Schaltfläche Weiter.
Sie können die Standardeinstellungen im Dialogfeld Android-Zielgeräte unverändert belassen. Klicken Sie erneut auf die Schaltfläche Weiter.


Scrollen Sie im Dialogfeld Aktivität zu Mobile hinzufügen nach unten und wählen Sie Aktivität mit Registerkarten aus. Klicken Sie danach auf die Schaltfläche Weiter.


Scrollen Sie im letzten Dialog nach unten zum Dropdown-Menü Navigationsstil und wählen Sie Aktionsleisten-Registerkarten (mit ViewPager). Klicken Sie abschließend auf die Schaltfläche Fertig stellen, um alle Konfigurationen zu akzeptieren.
Android Studio hat uns jetzt geholfen, ein Projekt mit einer Aktivität mit Registerkarten zu erstellen. Wirklich cool!


Es wird dringend empfohlen, den generierten Code zu erkunden.
Um diese Vorlage in einem bereits vorhandenen Android Studio-Projekt zu verwenden, gehen Sie einfach zu Datei > Aktivität > Aktivität mit Registerkarten. Und folgen Sie den ähnlichen Schritten, die zuvor beschrieben wurden.


Die in Android Studio enthaltenen Vorlagen eignen sich gut für einfache Layouts und die Erstellung einfacher Apps, aber wenn Sie Ihre App noch weiter starten möchten, sollten Sie einige der App-Vorlagen in Betracht ziehen, die von Envato Market erhältlich sind.
Sie sind eine enorme Zeitersparnis für erfahrene Entwickler, da sie ihnen helfen, den Aufwand für die Erstellung einer App von Grund auf zu überwinden und ihre Talente stattdessen auf die einzigartigen und angepassten Teile der Erstellung einer neuen App zu konzentrieren.
Abschluss
In diesem Tutorial haben Sie gelernt, wie Sie mit der TabLayout- und ViewPager-API von Grund auf eine Benutzeroberfläche mit Registerkarten in Android erstellen. Wir haben auch untersucht, wie Sie die Android Studio-Vorlagen einfach und schnell verwenden können, um eine Benutzeroberfläche mit Registerkarten zu erstellen.
Ich empfehle dringend, die offiziellen Richtlinien zum Materialdesign für Registerkarten zu lesen, um mehr darüber zu erfahren, wie Sie Registerkarten in Android richtig gestalten und verwenden.
Um mehr über das Codieren für Android zu erfahren, lesen Sie einige unserer anderen Kurse und Tutorials hier auf Envato Tuts+!











