
Im Internet gibt es viele interessante animierte Vorlagen mit schönen Benutzeroberflächen für mobile Anwendungen, aber es gibt nicht viele Beispiele für die Implementierung dieser Schnittstellen. Trotz der Fülle verschiedener integrierter Frameworks und Tools im Android SDK ist es für Anfänger oft nicht einfach, eine schöne Benutzeroberfläche zu implementieren, auch mit einer vorgefertigten Vorlage.
In diesem Artikel werden wir versuchen, die vom Designer Ivan Parfyonov für das PLATES-Studio entwickelte Benutzeroberfläche zu implementieren.
Erstellen Sie zunächst zwei Fragmente:
RecyclerFragment
und
DetailsFragment
.
Android Transition Framework?
Das Android Transition Framework funktioniert gut, aber es gibt einige Nuancen. Erstens möchten wir, dass zumindest für API 19 alles für uns funktioniert, und zweitens müssen wir mehrere Benutzerelemente gleichzeitig animieren, von denen einige nur in einem Fragment vorhanden sind. Daher implementieren wir die Animation des Übergangselements (Shared Element Transition) manuell mit
ViewPropertyAnimator
.
Alles in Ordnung
- Wir berechnen die endgültigen Koordinaten des ausgewählten Elements aus der Liste (seine Koordinaten in
DerailsFragment
). Die Liste ist eine RecyclerView
. - Wir speichern die aktuellen Koordinaten (Koordinaten in
RecyclerFragment
) und übergeben sie an DetailsFragment
(dies ist für die umgekehrte Animation mit API <21 erforderlich). - Erstellen Sie eine Kopie des ausgewählten Elements aus der Liste.
- Wir machen das ausgewählte Element unsichtbar (keine Kopie, sondern das Element selbst);
- Fügen Sie die in Schritt 3 erstellte Kopie zum Stammlayout des übergeordneten Fragments hinzu. In unserem Fall handelt es sich um
RecyclerFragment
. - Wir starten die Animation der verbleibenden Schnittstellenelemente und verschieben die erstellte Kopie ab Schritt 1 an die endgültigen Koordinaten.
- Wenn die Animation beendet ist, erstellen Sie eine Transaktion und zeigen Sie
DetailsFragment
. - Wir starten die Animation von Schnittstellenelementen in
DetailsFragment
.
UI-Elemente Animation
Um die
Toolbar
zu animieren
Toolbar
erstellen wir eine zusätzliche
View
im
RecyclerFragment
und platzieren sie oben hinter dem Bildschirm. Diese
View
wird mit
DetailsFragment
im
DetailsFragment
in
DetailsFragment
(blaue Farbe auf
ViewPropertyAnimator
)
ViewPropertyAnimator
.
<View android:id="@+id/details_toolbar_helper" android:layout_width="wrap_content" android:layout_height="@dimen/details_toolbar_container_height" android:background="@color/colorPrimary" app:layout_constraintTop_toTopOf="parent"/>
BottomNavigationView
und
RecyclerView
Animationen
BottomNavigationView
ebenfalls mit
ViewPropertyAnimator
implementiert,
ViewPropertyAnimator
nicht kompliziert ist (Transparenz ändern und verschieben).
Ein bisschen vom Transition Framework
Mit einfachen Worten, dann erstellt das Android-Übergangsframework beim Animieren des Übergangselements eine Kopie des Inhalts dieses Übergangselements (z. B. Druckbildschirm), erstellt aus dieser Kopie eine ImageView und fügt dieses Bild der zusätzlichen Überlagerungsebene in der Überlagerungsebene hinzu das aufgerufene Fragment und startet die Animation.
Das Android Transition Framework ist für uns nicht ganz geeignet, weil Wenn die Übergangselementanimation beginnt, werden alle anderen Elemente der Benutzeroberfläche im Fragment zerstört und können nicht animiert werden. Das heißt, Wenn wir in
RecyclerFragment
auf ein Listenelement klicken, um
DetailsFragment
zu öffnen und eine Übergangsanimation zu starten, werden alle anderen Oberflächenelemente in
RecyclerFragment
ohne Animation zerstört.
Um das gewünschte Ergebnis zu erzielen, erstellen wir manuell eine Kopie des aus der Liste ausgewählten Elements, fügen es der Überlagerungsebene hinzu und animieren es dann. Hier tritt jedoch ein kleines Problem auf. In der Dokumentation zur
ViewGroupOverlay add(view: View)
Methode
ViewGroupOverlay add(view: View)
heißt es:
Wenn die Ansicht ein übergeordnetes Element hat, wird die Ansicht von diesem übergeordneten Element entfernt, bevor sie dem Overlay hinzugefügt wird.
Bei
RecyclerView
funktioniert dies jedoch nicht. Das ausgewählte Element wird nicht aus
RecyclerView
gelöscht, nachdem es der Überlagerungsebene hinzugefügt wurde.
Folgendes passiert, wenn wir das ausgewählte Element zur Überlagerungsebene hinzufügen:
Und wir brauchen das:
Daher werden wir die Überlagerungsebene nicht verwenden und die Kopie sofort zum Stammlayout hinzufügen. Erstellen Sie eine Kopie des Inhalts des ausgewählten Elements, fügen Sie es der
ImageView
und legen Sie die Koordinaten fest:
fun View.copyViewImage(): View { val copy = ImageView(context) val bitmap = drawToBitmap() copy.setImageBitmap(bitmap) // pre-Lollipop , card view , card view return (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { CardView(context).apply { cardElevation = resources.getDimension(R.dimen.card_elevation) radius = resources.getDimension(R.dimen.card_corner_radius) addView(copy) } } else { copy }).apply { layoutParams = this@copyViewImage.layoutParams layoutParams.height = this@copyViewImage.height layoutParams.width = this@copyViewImage.width x = this@copyViewImage.x y = this@copyViewImage.y } }
Warum eine Kopie erstellen, wenn Sie nur das direkt ausgewählte Element aus der Liste animieren können?Weil
RecyclerView
selbst auch animiert wird und dementsprechend alle seine Elemente, einschließlich des ausgewählten, die wir separat animieren möchten.
Fügen Sie danach eine Kopie zum Root-Markup hinzu und starten Sie die Animation.
override fun onClick(view: View) { val fragmentTransaction = initFragmentTransaction(view) val copy = view.createCopyView() root.addView(copy) view.visibility = View.INVISIBLE startAnimation(copy, fragmentTransaction) }
Und hier ist was wir haben:
Ziellinie
Die obige GIF-Animation findet in einem
RecyclerFragment
. Nach dessen Abschluss müssen wir
DetailsFragment
.
.withEndAction { fragmentTransaction?.commitAllowingStateLoss() }
Warum verwenden wir commitAllowingStateLoss
?Wenn Sie es nicht verwenden und sich zum Zeitpunkt der Animation beispielsweise die Ausrichtung des Bildschirms ändert, erhalten wir
IllegalStateExeption
.
Hier ist es gut darüber geschrieben.
Als Nächstes starten wir die Animation der erforderlichen Elemente der Benutzeroberfläche in
DetailsFragment
.
Führen Sie alles zusammen
Nicht ganz das gleiche wie das Original, aber es sieht ähnlich aus.
Beispiele
Der Quellcode ist auf
GitHub verfügbar, und der Artikel ist auch in
englischer Sprache verfügbar.
Vielen Dank für Ihre Aufmerksamkeit!