Die Fragment API bietet zwei Möglichkeiten, Bewegungseffekte und Transformationen zu verwenden
um Fragmente während der Navigation visuell zu verbinden. Eine davon ist die
Animation Framework, das sowohl
Animation
und
Animator
Die
Das andere ist das Framework für die Umstellung, das Folgendes umfasst:
von gemeinsam genutzten Elementen.
Sie können benutzerdefinierte Effekte für das Ein- und Ausblenden von Fragmenten sowie für Übergänge gemeinsam genutzter Elemente zwischen Fragmenten.
- Mit dem Eingabe-Effekt wird festgelegt, wie ein Fragment auf dem Bildschirm erscheint. Beispiel: können Sie einen Effekt erzeugen, um das Fragment vom Rand des wenn Sie dorthin navigieren.
- Ein Exit-Effekt bestimmt, wie ein Fragment den Bildschirm verlässt. Beispiel: können Sie einen Effekt erzeugen, um das Fragment beim Verlassen der Seite auszublenden. daraus entfernt werden.
- Durch einen Übergang mit gemeinsam genutzten Elementen wird festgelegt, wie eine Ansicht zwischen
zwischen zwei Fragmenten. Beispiel: Ein angezeigtes Bild
in einer
ImageView
in Fragment A geht einmal B zu Fragment B über. sichtbar wird.
Animationen festlegen
Zunächst müssen Sie Animationen für Ihre Ein- und Exit-Effekte erstellen. beim Navigieren zu einem neuen Fragment. Sie können Animationen als Tween-Animationsressourcen. Mit diesen Ressourcen können Sie definieren, wie Fragmente sich während der Animation bewegen. Vielleicht möchten Sie das aktuelle Fragment und das neue Fragment, das sich vom rechten Bildschirmrand öffnet, wie in Abbildung 1 dargestellt.
<ph type="x-smartling-placeholder">Diese Animationen können im Verzeichnis res/anim
definiert werden:
<!-- res/anim/fade_out.xml -->
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:anim/decelerate_interpolator"
android:fromAlpha="1"
android:toAlpha="0" />
<!-- res/anim/slide_in.xml -->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:anim/decelerate_interpolator"
android:fromXDelta="100%"
android:toXDelta="0%" />
Sie können auch Animationen für die Ein- und Ausstiegseffekte festlegen, die ausgeführt werden.
beim Heranzoomen des Back-Stacks, was passieren kann, wenn Nutzende auf die Schaltfläche
Schaltfläche „Zurück“ Diese werden als popEnter
- und popExit
-Animationen bezeichnet. Für
Wenn z. B. ein Nutzer zu einem vorherigen Bildschirm zurückkehrt,
Aktuelles Fragment, das vom rechten Bildschirmrand und vom vorherigen weg verschoben wird
Fragment, das eingeblendet werden soll.
Diese Animationen können so definiert werden:
<!-- res/anim/slide_out.xml -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:anim/decelerate_interpolator"
android:fromXDelta="0%"
android:toXDelta="100%" />
<!-- res/anim/fade_in.xml -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:anim/decelerate_interpolator"
android:fromAlpha="0"
android:toAlpha="1" />
Nachdem Sie Ihre Animationen definiert haben, rufen Sie
FragmentTransaction.setCustomAnimations()
,
und übergeben Ihre Animationsressourcen
anhand ihrer Ressourcen-ID, wie in den
folgendes Beispiel:
Kotlin
supportFragmentManager.commit { setCustomAnimations( R.anim.slide_in, // enter R.anim.fade_out, // exit R.anim.fade_in, // popEnter R.anim.slide_out // popExit ) replace(R.id.fragment_container, fragment) addToBackStack(null) }
Java
Fragment fragment = new FragmentB(); getSupportFragmentManager().beginTransaction() .setCustomAnimations( R.anim.slide_in, // enter R.anim.fade_out, // exit R.anim.fade_in, // popEnter R.anim.slide_out // popExit ) .replace(R.id.fragment_container, fragment) .addToBackStack(null) .commit();
Übergänge festlegen
Sie können Übergänge auch verwenden, um Ein- und Exit-Effekte zu definieren. Diese Übergänge können in XML-Ressourcendateien definiert werden. Zum Beispiel könnten Sie soll das aktuelle Fragment ausgeblendet und das neue Fragment rechten Bildschirmrand. Diese Übergänge können so definiert werden:
<!-- res/transition/fade.xml -->
<fade xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"/>
<!-- res/transition/slide_right.xml -->
<slide xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_shortAnimTime"
android:slideEdge="right" />
Nachdem Sie Ihre Übergänge definiert haben, wenden Sie sie an, indem Sie
setEnterTransition()
auf das eingegebene Fragment und
setExitTransition()
beim schließenden Fragment, wobei die überhöhten Übergangsressourcen übergeben werden
nach ihrer Ressourcen-ID sortiert, wie im folgenden Beispiel gezeigt:
Kotlin
class FragmentA : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val inflater = TransitionInflater.from(requireContext()) exitTransition = inflater.inflateTransition(R.transition.fade) } } class FragmentB : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val inflater = TransitionInflater.from(requireContext()) enterTransition = inflater.inflateTransition(R.transition.slide_right) } }
Java
public class FragmentA extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TransitionInflater inflater = TransitionInflater.from(requireContext()); setExitTransition(inflater.inflateTransition(R.transition.fade)); } } public class FragmentB extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TransitionInflater inflater = TransitionInflater.from(requireContext()); setEnterTransition(inflater.inflateTransition(R.transition.slide_right)); } }
Unterstützung von Fragmenten AndroidX-Übergänge Fragmente unterstützen zwar auch Framework-Umstellungen zu verfolgen, empfehlen AndroidX-Umstellungen, da diese in API-Levels 14 unterstützt werden. und höher und enthalten Fehlerbehebungen, die in älteren Versionen der Framework-Umstellungen.
Übergänge mit gemeinsam genutzten Elementen verwenden
Teil des Frameworks für die Umstellung
Übergänge mit gemeinsam genutzten Elementen bestimmen, wie
entsprechende Ansichten zwischen
während eines Fragmentübergangs zwei Fragmente. Zum Beispiel könnten Sie eine
Bild, das in einem ImageView
in Fragment A angezeigt wird, um zu Fragment B zu wechseln
sobald B sichtbar wird (siehe Abbildung 3).
Im Folgenden erfahren Sie, wie Sie einen Fragmentübergang mit gemeinsam genutzten Elementen erstellen:
- Weisen Sie jeder Ansicht gemeinsam genutzter Elemente einen eindeutigen Übergangsnamen zu.
- Fügen Sie gemeinsam genutzte Elementansichten und Übergangsnamen zum
FragmentTransaction
- Übergangsanimation für gemeinsam genutzte Elemente festlegen
Zunächst müssen Sie jeder Ansicht gemeinsam genutzter Elemente einen eindeutigen Übergangsnamen zuweisen.
damit die Ansichten von einem Fragment zum nächsten zugeordnet werden können. Legen Sie einen
Namen von gemeinsam genutzten Elementen in jedem Fragmentlayout mithilfe von
ViewCompat.setTransitionName()
,
und bietet Kompatibilität mit API-Levels 14 und höher.
Beispielsweise der Übergangsname für eine ImageView
in den Fragmenten A und B.
kann folgendermaßen zugewiesen werden:
Kotlin
class FragmentA : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... val itemImageView = view.findViewById<ImageView>(R.id.item_image) ViewCompat.setTransitionName(itemImageView, “item_image”) } } class FragmentB : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... val heroImageView = view.findViewById<ImageView>(R.id.hero_image) ViewCompat.setTransitionName(heroImageView, “hero_image”) } }
Java
public class FragmentA extends Fragment { @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { ... ImageView itemImageView = view.findViewById(R.id.item_image); ViewCompat.setTransitionName(itemImageView, “item_image”); } } public class FragmentB extends Fragment { @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { ... ImageView heroImageView = view.findViewById(R.id.hero_image); ViewCompat.setTransitionName(heroImageView, “hero_image”); } }
Um Ihre gemeinsam genutzten Elemente in den Fragmentübergang einzubeziehen,
FragmentTransaction
muss wissen, wie die Ansichten der geteilten Elemente von einem
zum nächsten Fragment. Fügen Sie jedes Ihrer gemeinsamen Elemente
FragmentTransaction
über folgenden Anruf
FragmentTransaction.addSharedElement()
,
übergeben die Ansicht und den Übergangsnamen der entsprechenden Ansicht im
nächstes Fragment, wie im folgenden Beispiel gezeigt:
Kotlin
val fragment = FragmentB() supportFragmentManager.commit { setCustomAnimations(...) addSharedElement(itemImageView, “hero_image”) replace(R.id.fragment_container, fragment) addToBackStack(null) }
Java
Fragment fragment = new FragmentB(); getSupportFragmentManager().beginTransaction() .setCustomAnimations(...) .addSharedElement(itemImageView, “hero_image”) .replace(R.id.fragment_container, fragment) .addToBackStack(null) .commit();
Um festzulegen, wie Ihre gemeinsam genutzten Elemente von einem Fragment zum nächsten übergehen,
müssen Sie auf dem zu verwendenden Fragment einen enter-Übergang festlegen.
aufgerufen wurde. Anruf
Fragment.setSharedElementEnterTransition()
in der Methode onCreate()
des Fragments, wie im folgenden Beispiel gezeigt:
Kotlin
class FragmentB : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) sharedElementEnterTransition = TransitionInflater.from(requireContext()) .inflateTransition(R.transition.shared_image) } }
Java
public class FragmentB extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Transition transition = TransitionInflater.from(requireContext()) .inflateTransition(R.transition.shared_image); setSharedElementEnterTransition(transition); } }
Der Übergang shared_image
ist so definiert:
<!-- res/transition/shared_image.xml -->
<transitionSet>
<changeImageTransform />
</transitionSet>
Alle abgeleiteten Klassen von Transition
werden als Übergänge mit gemeinsam genutzten Elementen unterstützt. Wenn
Sie ein benutzerdefiniertes Transition
erstellen möchten, finden Sie unter
Benutzerdefinierte Übergangsanimation erstellen
changeImageTransform
, das im vorherigen Beispiel verwendet wurde, ist eine der verfügbaren
vordefinierte Übersetzungen, die Sie nutzen können. Hier finden Sie weitere Transition
in der API-Referenz für die
Klasse Transition
.
Standardmäßig wird der Übergang vom gemeinsam genutzten Element auch als
return-Übergang für gemeinsam genutzte Elemente. Der Rückübergang bestimmt, wie
gemeinsam genutzte Elemente gehen zum vorherigen Fragment über,
Transaktion aus dem Back-Stack entfernt. Falls Sie eine andere
können Sie dies mithilfe der
Fragment.setSharedElementReturnTransition()
in der Methode onCreate()
des Fragments.
Vorausschauende Rückenkompatibilität
Sie können die Funktion „Hintergrundeingabe“ mit vielen, aber nicht allen fragmentierten Animationen verwenden. Beachten Sie bei der Implementierung von „rückblickender Prognose“ Folgendes:
- Importieren Sie
Transitions 1.5.0
oder höher undFragments 1.7.0
oder höher. - Die
Animator
-Klasse und die abgeleiteten Klassen sowie die AndroidX-Übergangsbibliothek sind unterstützt. - Die
Animation
-Klasse und die Framework-Transition
-Bibliothek werden nicht unterstützt. - Prognostische Fragmentanimationen funktionieren nur auf Geräten mit Android 14 oder höher liegen.
setCustomAnimations
,setEnterTransition
,setExitTransition
setReenterTransition
,setReturnTransition
setSharedElementEnterTransition
undsetSharedElementReturnTransition
sind mit der Funktion „Rückwärtspfeil“.
Weitere Informationen finden Sie unter Unterstützung für vorausschauende Rückwärtsanimationen
Übergänge verschieben
In einigen Fällen müssen Sie den Fragmentübergang um einen in einem kurzen Zeitraum. Es kann z. B. sein, dass Sie warten müssen, bis alle Aufrufe im eingegebenen Fragment so vermessen und angeordnet wurden, dass Android ihre Start- und Endzustände für den Übergang genau erfassen.
Außerdem muss die Umstellung möglicherweise die erforderlichen Daten geladen wurden. Sie müssen z. B. warten, bis Bilder wurden für geteilte Elemente geladen. Andernfalls kann es passieren, wenn ein Bild während oder nach dem Übergang fertig geladen wird.
Um einen Übergang zu verschieben, müssen Sie zuerst sicherstellen, dass das Fragment
-Transaktion ermöglicht die Neuanordnung von Fragmentstatusänderungen. Um Neuanordnung zu ermöglichen
Änderungen des Fragmentstatus,
FragmentTransaction.setReorderingAllowed()
,
Dies wird im folgenden Beispiel gezeigt:
Kotlin
val fragment = FragmentB() supportFragmentManager.commit { setReorderingAllowed(true) setCustomAnimation(...) addSharedElement(view, view.transitionName) replace(R.id.fragment_container, fragment) addToBackStack(null) }
Java
Fragment fragment = new FragmentB(); getSupportFragmentManager().beginTransaction() .setReorderingAllowed(true) .setCustomAnimations(...) .addSharedElement(view, view.getTransitionName()) .replace(R.id.fragment_container, fragment) .addToBackStack(null) .commit();
Um den Wechsel zu verschieben, rufen Sie Folgendes auf:
Fragment.postponeEnterTransition()
in der Methode onViewCreated()
des eingegebenen Fragments:
Kotlin
class FragmentB : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... postponeEnterTransition() } }
Java
public class FragmentB extends Fragment { @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { ... postponeEnterTransition(); } }
Sobald Sie die Daten geladen haben und mit der Umstellung beginnen können, rufen Sie
Fragment.startPostponedEnterTransition()
Im folgenden Beispiel wird die Methode
Glide-Bibliothek, um ein Bild zu laden
in eine gemeinsame ImageView
, wobei der entsprechende Übergang bis zur
Ladevorgang ist abgeschlossen.
Kotlin
class FragmentB : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... Glide.with(this) .load(url) .listener(object : RequestListener<Drawable> { override fun onLoadFailed(...): Boolean { startPostponedEnterTransition() return false } override fun onResourceReady(...): Boolean { startPostponedEnterTransition() return false } }) .into(headerImage) } }
Java
public class FragmentB extends Fragment { @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { ... Glide.with(this) .load(url) .listener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(...) { startPostponedEnterTransition(); return false; } @Override public boolean onResourceReady(...) { startPostponedEnterTransition(); return false; } }) .into(headerImage) } }
Bei Problemen wie der langsamen Internetverbindung eines Nutzers
dass der verschobene Übergang
nach einer bestimmten Zeit beginnen soll,
als warten, bis alle Daten geladen sind. In diesen Fällen können Sie
stattdessen anrufen
Fragment.postponeEnterTransition(long, TimeUnit)
in der onViewCreated()
-Methode des eingegebenen Fragments, wobei die Dauer übergeben wird
und die Zeiteinheit. Die verschobene Anzeige beginnt dann automatisch,
die angegebene Zeit verstrichen ist.
Übergänge mit gemeinsam genutzten Elementen mit einem RecyclerView
verwenden
Verschobene
Eingabeübergänge sollten erst beginnen, wenn alle Ansichten in der
wurden vermessen und angeordnet. Bei Verwendung eines
RecyclerView
, Sie müssen warten
bis alle Daten geladen sind und die RecyclerView
-Elemente zum Zeichnen bereit sind
bevor Sie mit der Umstellung beginnen. Beispiel:
Kotlin
class FragmentA : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { postponeEnterTransition() // Wait for the data to load viewModel.data.observe(viewLifecycleOwner) { // Set the data on the RecyclerView adapter adapter.setData(it) // Start the transition once all views have been // measured and laid out (view.parent as? ViewGroup)?.doOnPreDraw { startPostponedEnterTransition() } } } }
Java
public class FragmentA extends Fragment { @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { postponeEnterTransition(); final ViewGroup parentView = (ViewGroup) view.getParent(); // Wait for the data to load viewModel.getData() .observe(getViewLifecycleOwner(), new Observer<List<String>>() { @Override public void onChanged(List<String> list) { // Set the data on the RecyclerView adapter adapter.setData(it); // Start the transition once all views have been // measured and laid out parentView.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw(){ parentView.getViewTreeObserver() .removeOnPreDrawListener(this); startPostponedEnterTransition(); return true; } }); } }); } }
Beachten Sie, dass ein
ViewTreeObserver.OnPreDrawListener
wird für das übergeordnete Element der Fragmentansicht festgelegt. So stellen Sie sicher, dass alle
die Ansichten des Fragments wurden gemessen und angeordnet und sind daher
vor Beginn des verschobenen Übergangs gezeichnet werden.
Ein weiterer Punkt, der bei der Verwendung von Übergängen mit gemeinsam genutzten Elementen in Verbindung mit einem
RecyclerView
ist, dass Sie den Übergangsnamen nicht in der
Das XML-Layout des RecyclerView
-Elements, da sich eine beliebige Anzahl von Elementen das gleiche teilen kann
für dieses Layout. Für den Übergang muss ein eindeutiger Name für den Übergang zugewiesen werden,
die richtige Ansicht verwendet.
Sie können dem gemeinsam genutzten Element einen eindeutigen Übergangsnamen zuweisen, indem Sie
Sie werden zugewiesen, wenn die ViewHolder
gebunden ist. Wenn zum Beispiel die Daten für
jeder Artikel eine eindeutige ID hat, kann dieser als Übergangsname verwendet werden,
Beispiel:
Kotlin
class ExampleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val image = itemView.findViewById<ImageView>(R.id.item_image) fun bind(id: String) { ViewCompat.setTransitionName(image, id) ... } }
Java
public class ExampleViewHolder extends RecyclerView.ViewHolder { private final ImageView image; ExampleViewHolder(View itemView) { super(itemView); image = itemView.findViewById(R.id.item_image); } public void bind(String id) { ViewCompat.setTransitionName(image, id); ... } }
Weitere Informationen
Weitere Informationen zu Fragmentübergängen finden Sie in den folgenden zusätzlichen Ressourcen.