Gestenverwaltung: Umgang mit visuellen Overlays. Teil 2

In Erwartung des Beginns eines Fortgeschrittenenkurses in Android-Entwicklung werden wir Ihnen weiterhin eine Reihe nützlicher Übersetzungen zur Verfügung stellen.





Sie lesen den zweiten Artikel in einer Reihe zum Gestenmanagement. Den ersten Teil finden Sie hier .

Im ersten Teil der Serie haben wir gelernt, wie Sie Ihre Anwendung „von Rand zu Rand“ auf dem Bildschirm positionieren. Leider kann diese Art der Anzeige dazu führen, dass sich einige Ihrer Ansichten über die Grenzen des Bereichs der Systemanzeigen hinaus befinden und somit für den Benutzer nicht sichtbar sind. In diesem Artikel erfahren Sie, wie Sie eine view so hinzufügen, dass der Betrieb der Systemanzeigen nicht gestört wird.

In diesem Artikel werde ich auf so etwas wie ein "UI-System" verweisen. Dies ist der Name einer beliebigen Systemschnittstelle auf dem Bildschirm, unabhängig davon, ob es sich um eine Navigationsleiste oder eine Statusleiste handelt. Es enthält auch eine Benachrichtigungsleiste.

Einsätze


Der Begriff Insets bereitet Android-Entwicklern in der Regel Angst, da zu Zeiten von Android Lollipop immer versucht wurde, den Arbeitsbereich der Statusleiste zu nutzen. Diese alte Frage zu StackOverflow hat beispielsweise eine sehr große Anzahl von Ansichten.

Einschübe zeigen, welche Komponenten des Bildschirms mit der Systemschnittstelle kreuzen, z. B. eine Navigationsleiste oder eine Statusleiste. Schnittmenge kann einfach bedeuten, dass Sie über Ihren Inhalten angezeigt werden. Hier können Sie jedoch auch Informationen zu Systemgesten abrufen. Mit dem Einschub können Sie versuchen, Konflikte zu lösen, indem Sie beispielsweise die view von den Rändern weg verschieben.

In Android werden Einfügungen durch die WindowInsets- Klasse und in AndroidX durch die WindowInsetsCompat- Klasse dargestellt. Beginnend mit Android Q haben wir 5 Arten von Einfügungen , die wir beim Erstellen von Anwendungsbildschirmen verwenden können. Welche Art von inset verwenden ist, hängt von der jeweiligen Situation ab. Schauen wir uns also jeden Typ einzeln an und sehen Sie.

Systemfenstereinsatz


Methode : getSystemWindowInsets ()

Der Systemfenstereinsatz ist heute der gebräuchlichste inset . Sie sind in API 1 in verschiedenen Formen vorhanden und werden in der view angezeigt, wenn die Systembenutzeroberfläche über Ihrer Anwendung (entlang der z-Achse) angezeigt wird. Häufige Beispiele sind die Statusleiste und die Navigationsleiste sowie manchmal die Bildschirmtastatur (IME).

Schauen wir uns ein Beispiel an, in dem Sie Systemfenster-Einfügungen verwenden müssen . Wir haben bereits einen FloatingActionButton (FAB) in der unteren Ecke des Bildschirms mit einem Einzug von 16 dpi (gemäß den Richtlinien ).


FAB in einer Google I / O-App, bevor es in Edge-to-Edge konvertiert wird

Nachdem wir die Schritte 1 und 2 des vorherigen Artikels ausgeführt haben , befinden sich unsere view hinter der Navigationsleiste:


FAB in der Google I / O-App nach dem Strecken auf Vollbild

Jetzt sehen Sie, dass sich Ihr Konferenzplan hinter der Navigationsleiste befindet, und genau das ist unser Ziel - ein noch intensiveres Erlebnis. Ausführlichere Informationen zum Arbeiten mit Listen / Gittern erhalten Sie später.

Kehren wir zum Beispiel zurück. Jetzt sehen Sie, dass das FAB ausgeblendet ist, was wiederum bedeutet, dass der Benutzer nicht darauf klicken kann. Diesen Darstellungskonflikt wollen wir vermeiden. Das Beispiel sieht bei Verwendung der Tastennavigation (wie im Bild) klarer aus, da sich das Bedienfeld höher befindet. Bei der Gesten-Navigation mit dynamischer Farbanpassung funktioniert dies. Beachten Sie jedoch, dass das System jederzeit auf ein durchscheinendes Scrim umschalten kann, was die Interaktionserfahrung stören kann.
Jetzt ist ein guter Moment, um Ihnen mitzuteilen, wie wichtig es ist, Ihre Anwendung in allen Navigationsmodi zu testen.

Wie gehen wir mit diesem visuellen Konflikt um? An diesem Punkt kommen Systemfenstereinsätze ins Spiel. Dort erfahren Sie, wo sich die Systemanzeigen in Ihrer Ansichtshierarchie befinden. Mit diesen Werten können Sie die Ansicht weiter von den Systemanzeigen entfernen.

Im obigen Beispiel befindet sich das FAB rechts unten, sodass wir die Werte von systemWindowInsets.bottom und systemWindowInsets.right , um den Einzug der view auf jeder Seite zu vergrößern und sie weiter von der Navigationsleiste zu entfernen.

Sobald wir dies tun, erhalten wir Folgendes:


Wir werden später darüber sprechen, wie dies implementiert wird.

TL DR: Systemfenster-Einschübe eignen sich am besten zum Verschieben / Einrücken interaktiver views , die nicht von Systemfenstern verdeckt werden sollten.

Abgreifbare Elementeinsätze


Methode : getTappableElementInsets ()

Weiter unten in der Liste finden Sie tippbare Elementeinfügungen , die gerade in Android Q angezeigt wurden . Sie sind den obigen Einfügungen im Systemfenster sehr ähnlich, reagieren jedoch auf die unterschiedliche Sichtbarkeit der Navigationsleiste.

TL; DR: wie bei tappable element insets : Sie können sie im Allgemeinen ignorieren und system window insets . Sie können zum Abschnitt mit den Gesteneinsätzen weiter unten springen oder mit dem Lesen fortfahren.

Abgriffbare Element-Insets definieren die minimalen Insets , die in einer interaktiven (abgriffbaren) Ansicht angewendet werden müssen. "Minimal" bedeutet in diesem Fall, dass der angewendete Wert immer noch zu einem Konflikt mit den Systemanzeigen führen kann. Dies unterscheidet sie von Systemfenster-Einfügungen , die immer darauf abzielen, Konflikte mit Systemanzeigen zu vermeiden.

Lassen Sie uns unser Beispiel mit einem FloatingActionButton verwenden , um den Unterschied in den Werten zu zeigen:


Die Ränder der Navigationsleiste werden in Pink angezeigt. Grün - FAB-Ränder mit einem bestimmten Einzug am unteren Rand.



Denken Sie daran, dass Sie niemals Werte aus der obigen Tabelle fest codieren können, da die Größe der Navigationsleiste geändert werden kann. Verwenden Sie Einfügungen, um Konflikte zu vermeiden.

Möglicherweise haben wir festgestellt, dass sich tappable element insets und system gesture insets verhalten, wenn sich das Gerät im Schaltflächennavigationsmodus befindet. Ein wesentlicher Unterschied wird sichtbar, wenn das Gerät die Gestensteuerung verwendet und die dynamische Farbanpassung aktiviert ist. In diesem Fall ist die Navigationsleiste transparent, was bedeutet, dass es theoretisch möglich ist, interaktive views darin anzuordnen, sodass der Einzug von unten 0 ist.

Obwohl insets keine Ahnung haben, wo sich Ansichten befinden sollen, können Sie mit tappbaren Element-Insets theoretisch etwas Ähnliches erhalten:



Es hat nicht perfekt geklappt, da sich die view sehr nahe an der Navigationsleiste befindet, was für den Benutzer nicht sehr praktisch ist.

In der Praxis werden fast alle Anwendungsfälle für tippbare Elementeinsätze besser mit Systemfenstereinsätzen behandelt.

Gesteneinsätze


Methoden : getSystemGestureInsets () und getMandatorySystemGestureInsets ()

Die nächste Art von insets , die wir betrachten werden, sind gesture insets , die in der Version von Android Q hinzugefügt wurden. Ich erinnere mich, dass Android Q einen neuen Gestensteuerungsmodus einführt, mit dem der Benutzer das Gerät mit zwei Berührungsgesten steuern kann, die wie folgt ausgeführt werden können:

  1. Wischen Sie horizontal von einem der Ränder der Anzeige. Dies löst die Rückgabeaktion aus.
  2. Wischen Sie vom unteren Rand des Displays nach oben. Auf diese Weise kann der Benutzer zu seinem Startbildschirm oder zu den zuletzt verwendeten Anwendungen wechseln.


Gesten-Demonstration in Android Q

Eingefügte Systemgesten geben Bereiche des Fensters wieder, in denen Systemgesten Vorrang vor Berührungsgesten in Ihrer Anwendung haben. Möglicherweise haben Sie bemerkt, dass ich oben zwei Methoden angegeben habe. Dies liegt an der Tatsache, dass es tatsächlich zwei Arten von Systemgesteneinfügungen gibt : Eine speichert alle Bereiche von Gesten und die zweite eine Teilmenge, die die obligatorischen Systemgesteneinfügungen enthält.

Systemgesten-Einfügungen


Für den Anfang haben wir Systemgesten-Einfügungen . Sie enthalten alle Bereiche auf dem Bildschirm, in denen Systemgesten Vorrang vor den Gesten Ihrer Anwendung haben. In Android Q bedeutet dies, dass Einschübe wie folgt aussehen, dh Einrückungen vom unteren Rand enthalten, damit eine Geste zum Startbildschirm zurückkehrt, Einrückungen links und rechts für eine Zurück-Geste:

  0 +--------------+ | | | System | 40 | Gesture | 40 | Insets | | | +--------------+ 60 

Wann werden sich Systemgesten als nützlich erweisen? Diese insets geben an, wo Systemgesten Vorrang haben. Sie können sie also verwenden, um Ansichten, die eine Wischgeste erfordern, proaktiv zu verschieben.

Beispiele sind ein Bildschirm , der sich von unten erstreckt , Wischbewegungen in Spielen und Karussells (wie ViewPager ). Im Allgemeinen können Sie diese insets , um sich von den Bildschirmrändern aus zu bewegen bzw. einzurücken.

Obligatorische Systemgesteneinfügungen


Obligatorische Systemgesteneinfügungen sind eine Teilmenge der Systemgesteneinfügungen und enthalten nur Bereiche, die nicht aus der Anwendung entfernt werden können (z. B. den Namen). Wir haben im Thema des nächsten Artikels ein wenig nach vorne geschaut, in dem wir uns mit dem Umgang mit Gesten-Konflikten befassen. Um den aktuellen Artikel zu verstehen, müssen Sie jedoch wissen, dass Anwendungen System-Gesten aus einigen Bereichen des Bildschirms entfernen können.

Obligatorische Systemgesteneinfügungen kennzeichnen Bereiche des Bildschirms, in denen Systemgesten immer Vorrang haben und obligatorisch sind. Unter Android Q ist der einzige obligatorische Bereich im Moment der Gestenbereich des Startbildschirms am unteren Bildschirmrand. Dies ist erforderlich, damit der Benutzer die Anwendung immer beenden kann.
Wenn Sie sich das Beispiel von Gesteneinsätzen auf einem Android Q-Gerät ansehen, sehen Sie Folgendes:

  0 0 +--------------+ +--------------+ | | | Mandatory | | System | | System | 40 | Gesture | 40 0 | Gesture | 0 | Insets | | Insets | | | | | +--------------+ +--------------+ 60 60 

Es ist zu sehen, dass die Systemgesteneinfügungen Einrückungen links, rechts und unten enthalten, während die erforderlichen Einrückungen nur Einrückungen von unten enthalten, sodass die Rückkehrgeste zum Startbildschirm normal funktioniert. Weitere Informationen zum Löschen von Gestenbereichen finden Sie im nächsten Artikel.

Stabile Einsätze


Methode : getStableInsets ()

Stabile Einfügungen sind die letzten Arten von Einfügungen, die auf Android verfügbar sind. Sie sind nicht besonders wichtig für die Verwaltung von Gesten, aber ich entschied, dass es sich lohnt, darüber zu sprechen.

Stabile Einfügungen beziehen sich auf Systemfenstereinfügungen , zeigen jedoch an, wo die Systemschnittstelle über Ihrer Anwendung angezeigt werden kann und nicht, wo sie im Prinzip angezeigt wird. Stabile Einschübe werden hauptsächlich verwendet, wenn die Systemschnittstelle so konfiguriert ist, dass ihre Sichtbarkeit ein- oder ausgeschaltet werden kann, z. B. mithilfe von Lean-Back- oder Immersive- Modi (z. B. Spiele, Anzeigen von Fotos und Video-Playern).

Umgang mit Insets


Ich hoffe, Sie haben ein besseres Verständnis für die verschiedenen Arten von Einfügungen. Lassen Sie uns nun sehen, wie Sie sie in Ihren Anwendungen verwenden können.

Die Hauptmethode für den Zugriff auf WindowInsets ist die Methode setOnApplyWindowInsetsListener . Schauen wir uns eine Beispielansicht an, in die wir einrücken möchten, damit sie nicht hinter der Navigationsleiste angezeigt wird:

 ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets -> v.updatePadding(bottom = insets.systemWindowInsets.bottom) // Return the insets so that they keep going down the view hierarchy insets } 

Hier setzen wir einfach den unteren Einzug der view auf den unteren Einzugswert des Systemfensters .

Hinweis : Wenn Sie dies in einer ViewGroup tun , möchten Sie wahrscheinlich android:clipToPadding="false" . Dies liegt daran, dass standardmäßig alle Arten von Clip-Zeichnungen eingerückt sind . Dieses Attribut wird häufig in Verbindung mit RecyclerView verwendet , auf das im nächsten Artikel näher eingegangen wird.

Stellen Sie sicher, dass Ihre Hörfunktion nicht zu stark ist. Wenn es mehrmals mit denselben Einschüben aufgerufen wird, sollte das Ergebnis jedes Mal identisch sein. Ein Beispiel für eine nicht idempotente Funktion ist unten angegeben:

 ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets -> v.updatePadding(bottom = v.paddingBottom + insets.systemWindowInsets.bottom) insets } 

Bei jedem Aufruf der Listen-Funktion sollte der Einzug der Ansicht nicht größer sein (ala + =). Fenstereinsätze können jederzeit und mehrmals während der Gültigkeitsdauer der Ansichtshierarchie auftreten .

Jetpack


Eine andere Sache, die ich zu beachten empfehle , ist die Verwendung der WindowInsetsCompat- Klasse von Jetpack , unabhängig von Ihrer minimalen SDK-Version. Die WindowInsets-API wurde im Laufe der Jahre verbessert und erweitert. Die kompatible Version bietet API-Konsistenz und -Verhalten auf allen API-Ebenen.

Wenn die in Android Q verfügbaren neuen Arten von Insets betroffen sind , handelt es sich bei der Kompatibilitätsmethode um eine Reihe von Werten, die für das Hostgerät auf allen API-Ebenen gültig sind. Um auf die neuen APIs in Android X zuzugreifen , aktualisieren Sie sie auf androidx.core:core:1.2.0-xxx (jetzt in Alpha) oder höher. Hier finden Sie die neueste Version.

Gehen wir noch weiter


Die oben genannten Methoden sind die einfachste Möglichkeit, die WindowInsets [Compat] -API zu verwenden, können jedoch dazu führen, dass Ihr Code zu lang und zu lang wird. Zuvor schrieb ich einen Artikel, in dem ich ausführlich Methoden beschrieb, die die Ergonomie der Verarbeitung von Fenstereinsätzen mithilfe von Adapterbindern erheblich verbessern können. Sie können es hier lesen.

Im nächsten Artikel erfahren Sie, wie Sie mit Konflikten umgehen, die zwischen den Gesten Ihrer Anwendungen und den Systemgesten auftreten können.

Das ist alles. Wir warten auf alle beim kostenlosen Webinar , in dem unser Spezialist ausführlich über den Kurs spricht.

Source: https://habr.com/ru/post/de480778/


All Articles