Toolbar返回箭头转叉号动画仅首次生效问题求助
Hey there, this is a super common gotcha with AnimatedVectorDrawableCompat—once the animation finishes, it sticks to the final frame by default, and doesn't automatically reset to the starting state when you trigger it again. That's why you're seeing the cross icon pop up instantly instead of the animation playing after the first run.
Here are a few solid solutions to fix this, depending on your code structure:
1. Reset the AVD state before each playback
The simplest fix is to manually reset the animation's progress to 0 every time you want to play it. This ensures it starts from the beginning every time.
private boolean isShowingBackArrow = true; private void toggleToolbarNavAnimation() { AnimatedVectorDrawableCompat animDrawable; // Pick the correct animation based on current state if (isShowingBackArrow) { animDrawable = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_back_to_cross); } else { animDrawable = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_cross_to_back); } if (animDrawable != null) { // Critical step: Reset animation to start from frame 0 animDrawable.reset(); // Set as toolbar's home indicator getSupportActionBar().setHomeAsUpIndicator(animDrawable); // Start the animation animDrawable.start(); // Flip the state flag isShowingBackArrow = !isShowingBackArrow; } }
2. Control animation with ObjectAnimator for more flexibility
If you want finer control over the animation lifecycle, you can use ObjectAnimator to bind and trigger the animation. This makes resetting and replaying more reliable:
private AnimatedVectorDrawableCompat currentNavAnim; private void playNavAnimation() { // Clean up any existing animation first if (currentNavAnim != null) { currentNavAnim.stop(); currentNavAnim.reset(); } // Choose the animation resource int animRes = isShowingBackArrow ? R.drawable.avd_back_to_cross : R.drawable.avd_cross_to_back; currentNavAnim = AnimatedVectorDrawableCompat.create(this, animRes); getSupportActionBar().setHomeAsUpIndicator(currentNavAnim); // Use ObjectAnimator to drive the animation (alternatively, just call currentNavAnim.start()) ObjectAnimator animator = ObjectAnimator.ofInt(currentNavAnim, "currentPlayTime", 0, currentNavAnim.getDuration()); animator.setDuration(currentNavAnim.getDuration()); animator.start(); isShowingBackArrow = !isShowingBackArrow; }
3. Create a new AVD instance every time
Reusing the same AVD instance can cause state retention issues. Instead, instantiate a fresh copy each time you need to toggle the animation:
// Call this method whenever you need to switch the nav icon animation private void switchNavAnimation() { int targetAnimRes = isShowingBackArrow ? R.drawable.avd_back_to_cross : R.drawable.avd_cross_to_back; AnimatedVectorDrawableCompat newAnim = AnimatedVectorDrawableCompat.create(this, targetAnimRes); if (newAnim != null) { getSupportActionBar().setHomeAsUpIndicator(newAnim); newAnim.start(); isShowingBackArrow = !isShowingBackArrow; } }
Bonus Tip: Update in onPrepareOptionsMenu
If your animation is tied to fragment switches or dynamic toolbar state changes, make sure you update the animation in onPrepareOptionsMenu instead of just onCreateOptionsMenu—since onCreateOptionsMenu only runs once when the menu is first created:
@Override public boolean onPrepareOptionsMenu(Menu menu) { // Refresh the navigation animation state here switchNavAnimation(); return super.onPrepareOptionsMenu(menu); }
内容的提问来源于stack exchange,提问作者Chathuranga Shan

