2

互いに積み重なった 3 つのビューをアニメーション化しています。前面ビューではないビューをタップすると、1 つまたは 2 つのビューが上下にスライドしてタップされたビューを明らかにし、タップしたビューを前面に移動してから、すべてを元の位置に戻します。これらのほとんどは正常に動作します。アニメーション化したばかりのビューを前面に持ってきたときにのみ、ちらつきが目立ちます。

少なくとも 100 件の投稿を読みましたが、解決策が含まれている投稿はありません。提案されたすべての解決策を 1 か所にまとめ、できれば解決策を見つけるために、これを投稿しています。

アニメーションはビュー自体をアニメーション化するのではなく、単なる画像であることを知っています。ビューは元の位置にとどまります。それと関係があるのは間違いない。移動したばかりのビューを前面に持ってくる場合にのみ発生します。

アニメーションを開始する前またはアニメーションが終了した後にビューをアニメーションの終了位置に移動しても、少しは役に立ちません。

またAnimationListener.onAnimationEnd、私は独自の見解を導き出し、そこでインターセプトしたため、バグとは関係ありませんonAnimationEnd

と を使用Animation.setFillAfterAnimation.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;
  }
}

ImagePanel.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>

testpattern.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

bringToFront()アニメーション中に呼び出すと、同じ問題が発生しました。

アニメートしている子を含むsetChildrenDrawingOrderEnabled(boolean enabled)getChildDrawingOrder(int childCount, int i)を使用することで、問題を解決できました。ViewGroup

于 2013-05-23T14:56:06.097 に答える
0

に電話animation.cancel()してみてくださいonAnimationEnd。しばらく前に、コードを実行した後にアニメーションがちらつくという同様の問題があり、それでonAnimationEndうまくいったことを覚えています。

于 2012-07-29T19:04:29.253 に答える
0

いつでもすべての画像を表示する必要がありますか? 邪魔にならないように、可視性を非表示に設定できます。それらが必要になったら、それらを再び表示します。

于 2012-07-25T05:23:53.557 に答える