2

我正在为三个相互堆叠的视图制作动画。当我点击一个不是前视图的视图时,一个或两个视图会向上或向下滑动以打开被点击的视图,将被点击的视图放在前面,然后将所有内容返回到它们的原始位置。其中大部分工作正常。只有当我将一个我刚刚动画化的视图带到前面时,我才会看到明显的闪烁。

我已经阅读了至少一百篇文章,但没有一篇包含解决方案。我发布此内容是为了将每个建议的解决方案整合到一个地方,并希望找到解决方案。

我知道动画不会动画视图本身,而只是一个图像。视图保持在其原始位置。这肯定与此有关。仅在将刚刚移动的视图置于前面时才会发生这种情况。

在开始动画之前或动画结束之后将视图移动到动画结束位置并没有一点帮助。

它也与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>
4

3 回答 3

0

您是否需要随时可见所有图像?您可以将它们的可见性设置为不可见,这样它们就不会打扰您。一旦你需要它们,你就可以让它们再次可见。

于 2012-07-25T05:23:53.557 回答
0

尝试呼入animation.cancel()onAnimationEnd我记得前段时间我在执行代码后遇到了类似的动画闪烁问题,onAnimationEnd这就是诀窍。

于 2012-07-29T19:04:29.253 回答
0

bringToFront()在动画期间调用时,我观察到了同样的问题。

我可以通过使用包含我正在制作动画的孩子的setChildrenDrawingOrderEnabled(boolean enabled)和来解决我的问题。getChildDrawingOrder(int childCount, int i)ViewGroup

于 2013-05-23T14:56:06.097 回答