我正在为三个相互堆叠的视图制作动画。当我点击一个不是前视图的视图时,一个或两个视图会向上或向下滑动以打开被点击的视图,将被点击的视图放在前面,然后将所有内容返回到它们的原始位置。其中大部分工作正常。只有当我将一个我刚刚动画化的视图带到前面时,我才会看到明显的闪烁。
我已经阅读了至少一百篇文章,但没有一篇包含解决方案。我发布此内容是为了将每个建议的解决方案整合到一个地方,并希望找到解决方案。
我知道动画不会动画视图本身,而只是一个图像。视图保持在其原始位置。这肯定与此有关。仅在将刚刚移动的视图置于前面时才会发生这种情况。
在开始动画之前或动画结束之后将视图移动到动画结束位置并没有一点帮助。
它也与AnimationListener.onAnimationEnd
错误无关,因为我得出了自己的观点并onAnimationEnd
在那里拦截。
我正在使用Animation.setFillAfter
并将Animation.setFillEnabled
最终图像保留在动画结束位置。
我试过使用Animation.setZAdjustment
,但那个只适用于整个屏幕,而不是屏幕内的视图。
从我了解到的情况来看,我怀疑问题bringToFront()
本身就是removeChild()/addChild()
父视图。可能是removeChild
导致重绘显示没有删除子项的视图的原因。
所以我的问题是:有没有人看到我错过的任何可以解决这个问题的东西?Android是否可能有命令暂时停止绘图并稍后恢复绘图。有点像一setUpdateScreen(false) / setUpdateScreen(true)
对?这将允许我跳过闪烁阶段。
演示效果的最少代码如下。点击白色可以看到红色在白色后面上下移动而不闪烁(白色出现在前面但不移动)。然后点击红色以查看红色从白色后面向上移动,当它被带到前面时闪烁,就在它滑回白色之前。奇怪的是,当使用蓝色而不是红色时,同样的事情并不总是发生。
MainActivity.java
package com.example.testapp;
import com.example.testapp.ImagePanel.AnimationEndListener;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.TranslateAnimation;
public class MainActivity extends Activity
{
private static final int ANIMATION_TIME = 1000;
private ImagePanel mRed;
private ImagePanel mWhite;
private ImagePanel mBlue;
private int mFrontPanelId;
private void animate(final ImagePanel panel, final int yFrom, final int yTo,
final AnimationEndListener animationListener)
{
final TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 0, 0, yFrom, 0, yTo);
anim.setDuration(ANIMATION_TIME);
anim.setFillAfter(true);
anim.setFillEnabled(true);
if (animationListener != null)
{
panel.setAnimListener(animationListener);
}
panel.startAnimation(anim);
}
public void onClick(final View v)
{
final int panelId = v.getId();
if (mFrontPanelId == panelId)
{
return;
}
final ImagePanel panel = (ImagePanel) v;
final int yTop = mWhite.getTop() - mRed.getBottom();
final int yBot = mWhite.getBottom() - mBlue.getTop();
final boolean moveRed = panelId == R.id.red || mFrontPanelId == R.id.red;
final boolean moveBlue = panelId == R.id.blue || mFrontPanelId == R.id.blue;
animate(mBlue, 0, moveBlue ? yBot : 0, null);
animate(mRed, 0, moveRed ? yTop : 0, new AnimationEndListener()
{
public void onBegin()
{
}
public void onEnd()
{
// make sure middle panel always stays visible
if (moveRed && moveBlue)
{
mWhite.bringToFront();
}
panel.bringToFront();
animate(mBlue, moveBlue ? yBot : 0, 0, null);
animate(mRed, moveRed ? yTop : 0, 0, new AnimationEndListener()
{
public void onBegin()
{
}
public void onEnd()
{
}
});
mFrontPanelId = panelId;
}
});
}
@Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRed = (ImagePanel) findViewById(R.id.red);
mWhite = (ImagePanel) findViewById(R.id.white);
mBlue = (ImagePanel) findViewById(R.id.blue);
mFrontPanelId = R.id.red;
}
}
图像面板.java
package com.example.testapp;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class ImagePanel extends ImageView
{
public interface AnimationEndListener
{
public void onBegin();
public void onEnd();
}
private AnimationEndListener mAnim = null;
public ImagePanel(final Context context)
{
super(context);
}
public ImagePanel(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public ImagePanel(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onAnimationEnd()
{
super.onAnimationEnd();
clearAnimation();
if (mAnim != null)
{
final AnimationEndListener anim = mAnim;
mAnim = null;
anim.onEnd();
}
}
@Override
protected void onAnimationStart()
{
super.onAnimationStart();
if (mAnim != null)
{
mAnim.onBegin();
}
}
public void setAnimListener(final AnimationEndListener anim)
{
mAnim = anim;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.example.testapp.ImagePanel
android:id="@+id/blue"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="#000080"
android:src="@drawable/testpattern"
android:onClick="onClick" />
<com.example.testapp.ImagePanel
android:id="@+id/white"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#808080"
android:src="@drawable/testpattern"
android:onClick="onClick" />
<com.example.testapp.ImagePanel
android:id="@+id/red"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
android:background="#800000"
android:src="@drawable/testpattern"
android:onClick="onClick" />
</RelativeLayout>
测试模式.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:startColor="#00000000"
android:endColor="#ffffffff" />
</shape>