You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Toolbar返回箭头转叉号动画仅首次生效问题求助

Fix AnimatedVectorDrawable Only Playing Once for Toolbar Back Arrow to Cross Animation

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:25:33