1

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)

Henry98
  • 571
  • 2
  • 12

2 Answers2

1

If you have several images you might want to:

  • Use a RecyclerView. This gives you more control over animations and decorations, and optimizes the memory usage at the same time. This answer will help you understand how to make your animations.

  • Make sure you are not constantly resizing your images. If the animation needs to handle images that are originally too big, it might impact on the quality of the animation (i.e. use thumbnails and fixed sizes in order to avoid costly computations)

    • For instance, if your original images are 600x800 but your image
      view has a centerCrop/fit/etc ending up occupying a space of 200x200, android will be doing a lot of resizing to match those settings. The more computations it does, the more chances you get of missing
      frames. In other words: what you experience is a low framerate,
      which happens when android is unable to finish all drawing
      computations in time for the next screen refresh.

      There are different problems you can attack:

      • Reduce the computations by using the right image sizes

      • Smaller images also mean less memory usage, which reduces the need of memory reallocation or forced garbage collection.

      • Avoid computing/rendering things that are invisible. Either because they are out of screen or because something overlaps them. In your case, recycler view might help to load only the images on your visible screen, instead of wasting space and computations on images that are out of sight at the moment.

  • Reduce the layout rewrite. Android tries to render only the sections with updates, instead of re-render all the screen. But if your layout forces other layouts to recalculate their size, you can end up forcing a whole resize. In your case, do not use LinearLayout to list images. Instead, use some layout that is actually designed for that sort of things. As I said, RecyclerView with the default LinearLayoutManager works very well.

  • Check if you have hardware acceleration turned on.
Community
  • 1
  • 1
Logain
  • 4,259
  • 1
  • 23
  • 32
  • What do you mean by "constantly resizing your image"? Or rather, how would I fix it so that the images are the correct size? I'm certain that you are on the correct track because I just made a clean project with nothing else but a couple ImageViews, and the problem still persists. So I'm certain it has something to do with the size of my images. – Henry98 Jul 29 '15 at 21:54
0

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

ajacian81
  • 7,419
  • 9
  • 51
  • 64