Occasional flickering between ImageViews when moved

时间:2015-07-28 16:14:44

标签: java android

I have a series of ImageViews that I programatically added into a LinearLayout, so they all end up horizontally lined up.

But when I try to use a TranslateAnimation to move all the images at once, a 1 pixel white gap flashes between every ImageView for about .02 seconds and then disappears. And this seems to consistently happen every 2 seconds or so.

    TranslateAnimation moveLeft = new TranslateAnimation(0, -1250, 0, 0);
    moveLeft.setDuration(10000);
    moveLeft.setFillAfter(true);

I make my ImageViews all at the same time before I move them. (Also, the ImageViews have all default settings) I've also confirmed that there are no white gaps between the ImageViews before I move them.

The flickering only happens when I set all the ImageViews's animations to moveLeft.

Also, here is the class in question :

public class Terrain {

Bitmap tile;
InputStream is;
ImageView imageViewPlatform;
Drawable tileDrawable;

ArrayList<ImageView> terrainArray = new ArrayList<ImageView>();
ArrayList<TranslateAnimation> moveLeftArray = new ArrayList<TranslateAnimation>();

int count = 0;
int terrainBlockNumber = 0;

boolean initialized = false;
TranslateAnimation moveLeft;

public void initialize(Activity activity){

    is = activity.getResources().openRawResource(+R.drawable.game_tile);
    tile = BitmapFactory.decodeStream(is);
    tileDrawable = new BitmapDrawable(activity.getResources(), tile);

    moveLeft = new TranslateAnimation(0, -1250, 0, 0);
    moveLeft.setDuration(10000);
    moveLeft.setFillAfter(true);

    initialized = true;
    Log.d("Terrain", "Terrain images are initialized.");
}

public void draw(Activity activity, LinearLayout linearLayout,
                 LinearLayout.LayoutParams layoutParams)  {
    if (!initialized) {
        throw new RuntimeException("initialize() method must " +
                "be called before the draw() method.");
    }else{
        terrainArray.add(new ImageView(activity));
        ++count;
        terrainArray.get(count-1).setImageDrawable(tileDrawable);
        linearLayout.addView(terrainArray.get(count-1), layoutParams);
    }
}

    public void move(Activity activity)  {

        terrainBlockNumber++;

        final int terrainAnimationBlock = terrainBlockNumber;

        moveLeft.setAnimationListener(new Animation.AnimationListener() {

            int currentCount =  terrainAnimationBlock;

            @Override
            public void onAnimationStart(Animation animation) {
                Log.d("Animation Started", "Block Number is " + currentCount);
            }

            @Override
            public void onAnimationEnd(Animation animation) {

                terrainArray.get(currentCount - 1).setVisibility(View.GONE);
                Log.d("Terrain Deletion", "Block number " +
                        currentCount + " has been deleted.");
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        terrainArray.get(terrainBlockNumber - 1).startAnimation(moveLeft);

        }
    }
}

This is the XML file for the activity

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.project.PlayActivity">

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/linearLayout"
    android:weightSum="1"
    android:layout_alignParentTop="true"
    android:layout_marginTop="200dp"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true">

</LinearLayout>

</RelativeLayout>

UPDATE :

Moving the entire LinearLayout does not seem to work either. Although, moving the entire LinearLayout isn't really helpful. It cuts off ImageViews that are off-screen.

But since you requested it, all I did was change the move method to :

public void move(LinearLayout linearLayout){
    linearLayout.setAnimation(moveLeft);
}

All the images did actually move at the same speed, and there is still the flickering between the images.

UPDATE 2

I have confirmed that it has something to do with my images/how they're formatted/the size of the images or something along those lines. If it is any help, the image I use is 95 X 84 pixels. (It's really tiny)

2 个答案:

答案 0 :(得分:0)

Try to put the ImageViews in a LinearLayout or other ViewGroup and animate the entire ViewGroup and see if that helps.

答案 1 :(得分:0)

如果您有多张图片,可能需要:

  • 使用RecyclerView。这使您可以更好地控制动画和装饰,并同时优化内存使用。 This answer将帮助您了解如何制作动画。

  • 确保您不会不断调整图片大小。如果动画需要处理原本太大的图像,则可能会影响动画的质量(即使用缩略图和固定大小以避免代价高昂的计算)

    • 例如,如果您的原始图像为600x800,但您的图像为 视图有一个centerCrop / fit / etc最终占用200x200的空间, android将进行大量调整以匹配这些设置。该 它做的计算越多,你失去的机会就越多 帧。换句话说:你所经历的是低帧率,
      当android无法完成所有绘图时发生这种情况 下次屏幕刷新的时间计算。

      你可以攻击不同的问题:

      • 使用正确的图像尺寸减少计算

      • 较小的图像也意味着更少的内存使用量,这减少了内存重新分配或强制垃圾收集的需要。

      • 避免计算/渲染不可见的东西。要么因为它们不在屏幕之外,要么是因为某些东西与它们重叠。在您的情况下,回收者视图可能有助于仅加载可见屏幕上的图像,而不是浪费空间和计算在目前看不见的图像上。

  • 减少布局重写。 Android尝试仅渲染具有更新的部分,而不是重新渲染所有屏幕。但是,如果您的布局强制其他布局重新计算其大小,则最终可能会强制执行整个调整大小。在您的情况下,使用LinearLayout列出图片。相反,使用一些实际上为这类事物设计的布局。正如我所说,RecyclerView默认LinearLayoutManager的效果非常好。

  • 检查是否已打开硬件加速。