我正在爲彼此堆疊的三個視圖設置動畫。當我點擊一個不是前視圖的視圖時,一個或兩個視圖會向上或向下滑動以揭示拍攝視圖,將拍攝視圖置於前方,然後將所有視圖恢復到原始位置。這些大多數工作正常。只有當我看到前面的動畫時,我纔會看到一個明顯的閃爍。Android bringToFront導致閃爍
我已閱讀至少一百個帖子,但沒有包含解決方案。 我張貼此來鞏固每個建議的解決方案在一個地方,並希望找到一個解決方案。
我知道動畫不會爲視圖本身設置動畫,而只是一個圖像。視圖保持原來的位置。這肯定與此有關。只有在將視圖移到剛移動的前方時纔會發生。
在開始動畫之前或動畫完成之後將視圖移動到動畫結束位置並沒有幫助。
它也與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;
}
}
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>
在演示應用程序中只有3張圖像,並且每個圖像的一部分始終可見。 其實我正在建設的應用程序有這個問題有更多的圖像,我確實使不可見的應用程序不可見。 – 2012-07-25 16:27:28