Android 2.3: Grow/Shrink animation bug?
For my application, I'm trying to add a [grow/shrink + alpha change] animation to each ImageView in my layout. I managed to get the animations working and have each of the animations persist after they're done by setting fillAfter=开发者_如何转开发"true" for both of my XML files (grow.xml and shrink.xml). However, there seems to be some weird animation bug that causes unselected images to grow and then 'snap' back to normal size when I set fillAfter="true for shrink.xml! Let me explain how the application works and then give a scenario so it becomes more clear:
Initially, all the images have their alpha levels set to 50%. When I click on a particular image, it will grow to 120% and its alpha level will become 100% ('light up' effect). When I click on another image, the previously selected image will shrink back to 100% and its alpha level will return to 50% and the currently selected image will grow as described previously.
In my layout, I have three, equal sized images placed in a row. I click the first image, then click the second one then click the first one again. Ok, no problems there. Now, I click on the third image and I get the weird snapping problem for the first image. Any idea how to fix this?
I've tried:
- image.setAlpha(...) to avoid having to set the alpha level in shrink.xml then calling fillAfter="true", but unfortunately that's an API 11 call
- setting the fillAfter attribute of only my alpha tags to true in shrink.xml
- calling image.startAnimation(fadeOut) right after a shrink animation but that looks horrible.
- Overriding onAnimationEnd(), but this call never gets reached(??)
shrink.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fillAfter="true">
<scale
android:fromXScale="1.2"
android:toXScale="1.0"
android:fromYScale="1.2"
android:toYScale="1.0"
android:duration="300"
android:pivotX="50%"
android:pivotY="50%"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.5"
android:duration="300"/>
</set>
grow.xml
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fillAfter="true">
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1.0"
android:toXScale="1.20"
android:fromYScale="1.0"
android:toYScale="1.20"
android:duration="300"
android:pivotX="50%"
android:pivotY="50%"
/>
<alpha
android:fromAlpha="0.5"
android:toAlpha="1.0"
android:duration="300"/>
</set>
fade_out.xml:
<?xml version="1.0" encoding="UTF-8"?>
<alpha
xmlns:android="http://schemas.android.com/apk/res/android"
android:startOffset="300"
android:fromAlpha="1.0"
android:toAlpha="0.5"
android:fillAfter="true">
</alpha>
main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<ImageView
android:id="@+id/image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:src="@drawable/image1"/>
<ImageView
android:id="@+id/image2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:src="@drawable/image2"/>
<ImageView
android:id="@+id/image3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:src="@drawable/image3"/>
</LinearLayout>
Test.java:
public class Test extends Activity {
private View mSelected;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
final Animation grow = AnimationUtils.loadAnimation(this, R.anim.grow);
final Animation shrink = AnimationUtils.loadAnimation(this, R.anim.shrink);
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (mSelected == v)
return;
if (mSelected != null)
mSelected.startAnimation(shrink);
mSelected = v;
mSelected.startAnimation(grow);
}
};
ImageView image1 = (ImageView)findViewById(R.id.image1);
image1.startAnimation(fadeOut);
image1.setOnClickListener(listener);
ImageView image2 = (ImageView)findViewById(R.id.image2);
image2.startAnimation(fadeOut);
image2.setOnClickListener(listener);
ImageView image3 = (ImageView)findViewById(R.id.image3);
image3.startAnimation(fadeOut);
image3.setOnClickListener(listener);
}}
The problem is that your shrink Animation is still assigned to the other Views. When you're calling mSelected.startAnimation() you are starting the Animation object, which is attached to the other Views, so they animate as well. You can create a new instance of the Animation by changing mSelected.startAnimation(shrink);
to
mSelected.startAnimation(AnimationUtils.loadAnimation(Test.this, R.anim.shrink));
Which is the easy (though inefficient) way to solve the problem, or you can manage the Animation cycle yourself by unassigning Animations from Views (mSelected.setAnimation(null)
).
精彩评论