Why doesn't setVisibility work after a view is animated?

27,972

Solution 1

For me calling clearAnimation of the View fixed the problem. In my case I wanted to set the View back to its original position after doing a translation with fillAfter set to true.

Solution 2

All the animations (before android 3.0) are actually applied to a bitmap which is a snapshot of your view instead of on your original view. When you are setting the fill after to true this actually means that the bitmap will continue to be displayed on the screen instead of your view. This is the reason why the visibility won't change upon using setVisibility and also the reason why your view will not be receiving touch events in its new (rotated) bounds. (but since you're rotating on 180 degrees that's not an issue).

Solution 3

Another way to work around this is to wrap your animated view in another view and set the visibility of that wrapper view.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
    <FrameLayout 
        android:id="@+id/animationHoldingFrame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView
             android:id="@+id/tvRotate"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Rotate Me"
        />
    </FrameLayout>
</LinearLayout>

And the code then becomes this:

TextView tvRotate = (TextView) findViewById(R.id.tvRotate);
FrameLayout animationContainer = (FrameLayout)findViewById(R.id.animationHoldingFrame)

RotateAnimation r = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
r.setDuration(0);
r.setFillAfter(true);
tvRotate.startAnimation(r);
animationContainer.setVisibility(View.INVISIBLE);

Solution 4

I ended up requiring API Level 11 and using setRotation to accomplish this. This seems like a pretty simple requirement that can't be done pre-Honeycomb though. All i wanted to do was rotate a button and then hide/show it.

Solution 5

I came up with a workaround for this: basically right before you call setVisibility(View.GONE), do an animation with duration=0 setFillAfter(false) and have the angle from/to set to the current angle of rotation.

This will clear the setFillAfter bitmap and allow the view to be gone.

Share:
27,972
ZippyFerguson
Author by

ZippyFerguson

Updated on July 05, 2022

Comments

  • ZippyFerguson
    ZippyFerguson almost 2 years

    Why doesn't the textView become invisible?

    Here is my layout xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <TextView
        android:id="@+id/tvRotate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Rotate Me"
    />
    </LinearLayout>
    

    ..and here is my activity:

    public class RotateMeActivity extends Activity
    {
        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            TextView tvRotate = (TextView) findViewById(R.id.tvRotate);
    
            RotateAnimation r = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            r.setDuration(0);
            r.setFillAfter(true);
            tvRotate.startAnimation(r);
            tvRotate.setVisibility(View.INVISIBLE);
        }
    }
    

    My goal is to rotate a view and then be able to hide and show it in code by setting setVisibility. The following works, but setRotation is available only in API Level 11. I need a way to do it in API Level 10.

    tvRotate.setRotation(180);//instead of the RotateAnimation, only works in API Level 11
    tvRotate.setVisibility(View.INVISIBLE);
    
  • ZippyFerguson
    ZippyFerguson over 12 years
    so, is there any way to hide the bitmap that persists after the rotate?
  • Christopher Perry
    Christopher Perry over 11 years
    I was having this problem and can confirm that clearAnimation does the trick.
  • Dale Cooper
    Dale Cooper over 10 years
    please somebody accept this answer since that's the one that saves your a** after DAYS of struggling ;) thx!
  • czaku
    czaku about 10 years
    I confirm that this fixes the issue. To be more helpful use it in onAnimationEnd() in AnimationListener ;)
  • gak
    gak almost 10 years
    Does anyone know why this is needed? This fixed a problem I was having where the view did not remove itself from the parent.
  • Buddy
    Buddy almost 9 years
    jtietema, it would be better if you could add czaku's comment to your answer, thank you.
  • bstar55
    bstar55 almost 8 years
    Wow... I wasted so much time trying to figure this out. Great (and cryptic) solution!
  • Couitchy
    Couitchy over 7 years
    Exactly what I was looking for :-)
  • dbar
    dbar almost 7 years
    My visibility change was not working on API 19 because of a TransitionManager.delayedTransition. It was the animation on a marquee that was causing it and this fixed it.