Während der Nutzung deiner App werden neue Informationen auf dem Bildschirm angezeigt werden entfernt. Du kannst sofort ändern, was auf dem Bildschirm angezeigt wird, und Nutzer können neue Inhalte, die plötzlich angezeigt werden, übersehen. Animationen langsam die Änderungen herunter und ziehen das Auge der Nutzenden durch Bewegung, offensichtlicher.
Es gibt drei gängige Animationen, mit denen Sie eine Ansicht ein- oder ausblenden können: Anzeigen sowie Überblenden- und Cardflip-Animationen.
Überblendende Animation erstellen
Eine Überblendungsanimation, auch Überblenden genannt, wird allmählich ausgeblendet.
ein View
oder
ViewGroup
gleichzeitig
und in einem anderen überbrückt. Diese Animation eignet sich
zwischen Inhalten oder Ansichten in Ihrer App wechseln. Bei der hier gezeigten Überblendungsanimation wird
ViewPropertyAnimator
,
das für Android 3.1 (API-Level 12) und höher verfügbar ist.
Hier ist ein Beispiel für eine Überblendung von einer Fortschrittsanzeige zum Textinhalt:
Ansichten erstellen
Erstellen Sie die beiden Ansichten, die Sie überblenden möchten. Im folgenden Beispiel wird ein und eine scrollbare Textansicht:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum"
android:padding="16dp" />
</ScrollView>
<ProgressBar android:id="@+id/loading_spinner"
style="?android:progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
Überblendungsanimation einrichten
So richten Sie die Überblendungsanimation ein:
- Erstellen Sie Mitgliedervariablen für die Ansichten, die überblenden sollen. Du brauchst später beim Ändern der Ansichten während der Animation.
- Legen Sie die Sichtbarkeit der Ansicht fest, in die eingeblendet wird.
GONE
Dadurch wird verhindert, Layoutraum nicht verwendet und ihn bei den Layoutberechnungen auslässt, Verarbeitung läuft config_shortAnimTime
im Cache speichern Systemeigenschaft in einer Member-Variable fest. Diese Eigenschaft definiert ein standardmäßiges „kurzes“ Dauer der Animation. Diese Dauer eignet sich ideal für subtile Animationen oder Animationen erstellen, die häufig auftreten.config_longAnimTime
undconfig_mediumAnimTime
sind ebenfalls verfügbar.
Hier sehen Sie ein Beispiel, bei dem das Layout aus dem vorherigen Code-Snippet Ansicht der Aktivitätsinhalte:
Kotlin
class CrossfadeActivity : Activity() { private lateinit var contentView: View private lateinit var loadingView: View private var shortAnimationDuration: Int = 0 ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_crossfade) contentView = findViewById(R.id.content) loadingView = findViewById(R.id.loading_spinner) // Initially hide the content view. contentView.visibility = View.GONE // Retrieve and cache the system's default "short" animation time. shortAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime) } ... }
Java
public class CrossfadeActivity extends Activity { private View contentView; private View loadingView; private int shortAnimationDuration; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crossfade); contentView = findViewById(R.id.content); loadingView = findViewById(R.id.loading_spinner); // Initially hide the content view. contentView.setVisibility(View.GONE); // Retrieve and cache the system's default "short" animation time. shortAnimationDuration = getResources().getInteger( android.R.integer.config_shortAnimTime); } ... }
Überblenden Sie die Ansichten
Wenn die Ansichten richtig eingerichtet sind, können Sie sie folgendermaßen überblenden:
- Setze für die eingeblendete Ansicht den Alphawert auf 0 und die Sichtbarkeit
von Anfang an
VISIBLE
EinstellungGONE
. Dadurch wird die Ansicht sichtbar, aber transparent. - Animieren Sie für die eingeblendete Ansicht den Alphawert von 0 bis 1. Für die die ausgeblendete Ansicht, den Alphawert von 1 bis 0 animieren.
- Mit
onAnimationEnd()
in einemAnimator.AnimatorListener
, Sichtbarkeit der ausgeblendeten Ansicht aufGONE
festlegen Auch wenn die Alphawert 0 ist, wird mit der Sichtbarkeit der Ansicht aufGONE
verhindert, dass die Ansicht angezeigt wird. Layoutraum nicht verwendet und ihn bei den Layoutberechnungen auslässt, verarbeitet werden.
Die folgende Methode zeigt ein Beispiel dafür:
Kotlin
class CrossfadeActivity : Activity() { private lateinit var contentView: View private lateinit var loadingView: View private var shortAnimationDuration: Int = 0 ... private fun crossfade() { contentView.apply { // Set the content view to 0% opacity but visible, so that it is // visible but fully transparent during the animation. alpha = 0f visibility = View.VISIBLE // Animate the content view to 100% opacity and clear any animation // listener set on the view. animate() .alpha(1f) .setDuration(shortAnimationDuration.toLong()) .setListener(null) } // Animate the loading view to 0% opacity. After the animation ends, // set its visibility to GONE as an optimization step so it doesn't // participate in layout passes. loadingView.animate() .alpha(0f) .setDuration(shortAnimationDuration.toLong()) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { loadingView.visibility = View.GONE } }) } }
Java
public class CrossfadeActivity extends Activity { private View contentView; private View loadingView; private int shortAnimationDuration; ... private void crossfade() { // Set the content view to 0% opacity but visible, so that it is // visible but fully transparent during the animation. contentView.setAlpha(0f); contentView.setVisibility(View.VISIBLE); // Animate the content view to 100% opacity and clear any animation // listener set on the view. contentView.animate() .alpha(1f) .setDuration(shortAnimationDuration) .setListener(null); // Animate the loading view to 0% opacity. After the animation ends, // set its visibility to GONE as an optimization step so it doesn't // participate in layout passes. loadingView.animate() .alpha(0f) .setDuration(shortAnimationDuration) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { loadingView.setVisibility(View.GONE); } }); } }
Umblättern-Animation erstellen
Auf der Karte wird eine Animation gezeigt, die emuliert, um zwischen
eine Karte, die sich umdreht. In der hier gezeigten Animation
FragmentTransaction
So sieht ein Kartenumdrehen aus:
Animationsobjekte erstellen
Für die Animation zum Umdrehen der Karte benötigen Sie vier Animatoren. Zwei Animatoren sind wenn die Vorderseite der Karte nach außen und links und wenn nach links und rechts. Die anderen beiden Animatoren zeigen die Rückseite der Karte an. von rechts und dann nach rechts.
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="-180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 1. See startOffset. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 0. See startOffset. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Before rotating, immediately set the alpha to 0. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:duration="0" />
<!-- Rotate. -->
<objectAnimator
android:valueFrom="180"
android:valueTo="0"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 1. See startOffset. -->
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="-180"
android:propertyName="rotationY"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:duration="@integer/card_flip_time_full" />
<!-- Halfway through the rotation, set the alpha to 0. See startOffset. -->
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="@integer/card_flip_time_half"
android:duration="1" />
</set>
Ansichten erstellen
Jede Seite der Karte ist ein separates Layout, das alle Inhalte enthalten kann, wie etwa zwei Textansichten, zwei Bilder oder eine beliebige Kombination von Ansichten, die umgedreht werden sollen. dazwischen liegt. Verwenden Sie die beiden Layouts in den Fragmenten, die Sie später animieren. Die Mit dem folgenden Layout wird eine Seite einer Karte erstellt, auf der Text angezeigt wird:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#a6c"
android:padding="16dp"
android:gravity="bottom">
<TextView android:id="@android:id/text1"
style="?android:textAppearanceLarge"
android:textStyle="bold"
android:textColor="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_title" />
<TextView style="?android:textAppearanceSmall"
android:textAllCaps="true"
android:textColor="#80ffffff"
android:textStyle="bold"
android:lineSpacingMultiplier="1.2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/card_back_description" />
</LinearLayout>
Mit dem nächsten Layout wird die andere Seite der Karte erstellt,
ImageView
:
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/image1"
android:scaleType="centerCrop"
android:contentDescription="@string/description_image_1" />
Fragmente erstellen
Erstelle Fragmentklassen für die Vorder- und Rückseite der Karte. Im Fragment
werden die Layouts zurückgegeben, die Sie mit den
onCreateView()
. Sie können dann Instanzen dieses Fragments in der übergeordneten Aktivität erstellen
wo die Karte angezeigt werden soll.
Das folgende Beispiel zeigt verschachtelte Fragmentklassen innerhalb der übergeordneten Aktivität der sie verwendet:
Kotlin
class CardFlipActivity : FragmentActivity() { ... /** * A fragment representing the front of the card. */ class CardFrontFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_card_front, container, false) } /** * A fragment representing the back of the card. */ class CardBackFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = inflater.inflate(R.layout.fragment_card_back, container, false) } }
Java
public class CardFlipActivity extends FragmentActivity { ... /** * A fragment representing the front of the card. */ public class CardFrontFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_card_front, container, false); } } /** * A fragment representing the back of the card. */ public class CardBackFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_card_back, container, false); } } }
Kartenumdrehen animieren
Zeigt die Fragmente in einer übergeordneten Aktivität an. Erstellen Sie dazu das Layout
für Ihre Aktivität. Im folgenden Beispiel wird ein
FrameLayout
, die Sie hinzufügen können
zur Laufzeit fragmentiert:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Legen Sie im Aktivitätscode als Inhaltsansicht das von Ihnen erstellte Layout fest. Es empfiehlt sich, beim Erstellen der Aktivität ein Standardfragment anzuzeigen. Die Die folgende Beispielaktivität zeigt, wie Sie die Vorderseite der Karte Standardeinstellung:
Kotlin
class CardFlipActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_activity_card_flip) if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .add(R.id.container, CardFrontFragment()) .commit() } } ... }
Java
public class CardFlipActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_activity_card_flip); if (savedInstanceState == null) { getSupportFragmentManager() .beginTransaction() .add(R.id.container, new CardFrontFragment()) .commit(); } } ... }
Dabei können Sie die Rückseite der Karte mit den die Animation zum richtigen Zeitpunkt umdrehen. Erstellen Sie eine Methode, um die andere Seite eines die Karte, die folgende Aufgaben erfüllt:
- Legt die benutzerdefinierten Animationen fest, die Sie für die Fragmentübergänge erstellt haben.
- Ersetzt das angezeigte Fragment durch ein neues Fragment und animiert dieses Ereignis. mit den benutzerdefinierten Animationen, die Sie erstellt haben.
- Fügt das zuvor angezeigte Fragment zum Back Stack des Fragments hinzu. wenn der Nutzer auf die Schaltfläche „Zurück“ tippt, dreht sich die Karte wieder um.
Kotlin
class CardFlipActivity : FragmentActivity() { ... private fun flipCard() { if (showingBack) { supportFragmentManager.popBackStack() return } // Flip to the back. showingBack = true // Create and commit a new fragment transaction that adds the fragment // for the back of the card, uses custom animations, and is part of the // fragment manager's back stack. supportFragmentManager.beginTransaction() // Replace the default fragment animations with animator // resources representing rotations when switching to the back // of the card, as well as animator resources representing // rotations when flipping back to the front, such as when the // system Back button is tapped. .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out ) // Replace any fragments in the container view with a fragment // representing the next page, indicated by the just-incremented // currentPage variable. .replace(R.id.container, CardBackFragment()) // Add this transaction to the back stack, letting users press // the Back button to get to the front of the card. .addToBackStack(null) // Commit the transaction. .commit() } }
Java
public class CardFlipActivity extends FragmentActivity { ... private void flipCard() { if (showingBack) { getSupportFragmentManager().popBackStack(); return; } // Flip to the back. showingBack = true; // Create and commit a new fragment transaction that adds the fragment // for the back of the card, uses custom animations, and is part of the // fragment manager's back stack. getSupportFragmentManager() .beginTransaction() // Replace the default fragment animations with animator // resources representing rotations when switching to the back // of the card, as well as animator resources representing // rotations when flipping back to the front, such as when the // system Back button is pressed. .setCustomAnimations( R.animator.card_flip_right_in, R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out) // Replace any fragments in the container view with a fragment // representing the next page, indicated by the just-incremented // currentPage variable. .replace(R.id.container, new CardBackFragment()) // Add this transaction to the back stack, letting users press // Back to get to the front of the card. .addToBackStack(null) // Commit the transaction. .commit(); } }
Kreisförmige Animationsanimation erstellen
Einblenden-Animationen bieten Nutzern visuelle Kontinuität, wenn du eine Gruppe ein- oder ausblendest
von UI-Elementen. Die
ViewAnimationUtils.createCircularReveal()
können Sie einen Beschnittkreis animieren, um eine Ansicht ein- oder auszublenden. Dieses
Animation wird im
Klasse ViewAnimationUtils
,
das für Android 5.0 (API-Level 21) und höher verfügbar ist.
Hier ist ein Beispiel, das zeigt, wie eine zuvor unsichtbare Ansicht angezeigt wird:
Kotlin
// A previously invisible view. val myView: View = findViewById(R.id.my_view) // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. val cx = myView.width / 2 val cy = myView.height / 2 // Get the final radius for the clipping circle. val finalRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() // Create the animator for this view. The start radius is 0. val anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0f, finalRadius) // Make the view visible and start the animation. myView.visibility = View.VISIBLE anim.start() } else { // Set the view to invisible without a circular reveal animation below // Android 5.0. myView.visibility = View.INVISIBLE }
Java
// A previously invisible view. View myView = findViewById(R.id.my_view); // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // Get the final radius for the clipping circle. float finalRadius = (float) Math.hypot(cx, cy); // Create the animator for this view. The start radius is 0. Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0f, finalRadius); // Make the view visible and start the animation. myView.setVisibility(View.VISIBLE); anim.start(); } else { // Set the view to invisible without a circular reveal animation below // Android 5.0. myView.setVisibility(View.INVISIBLE); }
Die ViewAnimationUtils.createCircularReveal()
-Animation benötigt fünf Parameter.
Der erste Parameter ist die Ansicht, die auf dem Bildschirm ein- oder ausgeblendet werden soll. Die
Die nächsten beiden Parameter sind die X- und Y-Koordinaten für die Mitte des
. Normalerweise ist dies die Mitte der Ansicht. Sie können aber auch die
Punkt, den Nutzende antippen, damit die Animation dort beginnt, wo sie sie ausgewählt hat. Die
Der vierte Parameter ist der Startradius des begrenzenden Kreises.
Im vorherigen Beispiel ist der anfängliche Radius auf null gesetzt, sodass die Ansicht angezeigt wird, durch den Kreis ausgeblendet. Der letzte Parameter ist der endgültige Radius, des Kreises. Legen Sie bei der Anzeige einer Ansicht den letzten Radius größer als der -Ansicht, sodass die Ansicht vollständig aufgedeckt werden kann, bevor die Animation beendet ist.
So blenden Sie eine zuvor sichtbare Ansicht aus:
Kotlin
// A previously visible view. val myView: View = findViewById(R.id.my_view) // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. val cx = myView.width / 2 val cy = myView.height / 2 // Get the initial radius for the clipping circle. val initialRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() // Create the animation. The final radius is 0. val anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0f) // Make the view invisible when the animation is done. anim.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) myView.visibility = View.INVISIBLE } }) // Start the animation. anim.start() } else { // Set the view to visible without a circular reveal animation below // Android 5.0. myView.visibility = View.VISIBLE }
Java
// A previously visible view. final View myView = findViewById(R.id.my_view); // Check whether the runtime version is at least Android 5.0. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Get the center for the clipping circle. int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // Get the initial radius for the clipping circle. float initialRadius = (float) Math.hypot(cx, cy); // Create the animation. The final radius is 0. Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0f); // Make the view invisible when the animation is done. anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); } }); // Start the animation. anim.start(); } else { // Set the view to visible without a circular reveal animation below Android // 5.0. myView.setVisibility(View.VISIBLE); }
In diesem Fall ist der Anfangsradius des zu beschneidenden Kreises so groß wie
Ansicht, sodass die Ansicht sichtbar ist, bevor die Animation beginnt. Die letzte
radius wird auf null gesetzt, sodass die Ansicht ausgeblendet wird, wenn die Animation beendet ist.
Fügen Sie der Animation einen Listener hinzu, damit für die Sichtbarkeit der Ansicht folgender Wert festgelegt werden kann:
INVISIBLE
, wenn die Animation
abgeschlossen wird.
Weitere Informationen
- Animation mit Jetpack Compose.
- Touch-Gesten mit Jetpack Compose.