3
\$\begingroup\$

My question is about how to achieve a well-performing animation for a set of ImageViews, so that the foreground fades away and the background stays the same.

Currently, I'm writing a clone of "Color Lines" for Android using a GridLayout as a board and ImageViews as game pieces. Every ImageView uses the same (circular) ShapeDrawable:

ImageView ivChild.setImageResource(R.drawable.circle_shape);

where circle_shape.xml looks like this:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">

<gradient
    android:angle="0"
    android:centerColor="#eeeeee"
    android:centerX="0.0"
    android:centerY="0.0"
    android:endColor="#bbbbbb"
    android:startColor="#dddddd"
    android:type="sweep" />
</shape>

and another drawable resource as a background to get a board with tiles separated by thin lines (I'm using a rectangle shape with a color gradient and set a margin to the ImageViews).

screenshot of board

To show the differently colored items as well as the empty fields, I simply use setColorFilter() with different color resources (#00000000 for empty fields)

Every time the user completes a line of five or more items with the same color, I want to show an animation (color fading away) instead of just setting the color to transparent. I could simply use a ViewAnimation (alpha) if the whole View was to fade away but as I said I need to keep the background unchanged and just animate the foreground.

The following method is part of the Fragment which is hosting the board:

void clearPositions(int[] completedLinesPositions, color)
{
    ImageView[] fields = new ImageView[completedLinesPositions.length];
    for (int i = 0; i < completedLinesPositions.length; i++)
    {
        // board is the GridLayout
        fields[i] = (ImageView) board.getChildAt(positions[i]);
    }

    ValueAnimator animation = ValueAnimator.ofObject(new FloatEvaluator(), 1.0f, 0f);

    ValueAnimator.AnimatorUpdateListener myUpdateListener = new MyAlphaUpdateListener(fields, color);

    animation.addUpdateListener(myUpdateListener);
    animation.setDuration(200);
    animation.start();

    int empty = Color.argb(0, 0, 0, 0);
    for (ImageView iv: fields )
    {
        iv.clearColorFilter();
        iv.setColorFilter(empty, PorterDuff.Mode.MULTIPLY);
    }
}

The MyAlphaUpdateListener:

public class MyAlphaUpdateListener implements     ValueAnimator.AnimatorUpdateListener {

    private ImageView[] imageViews;
    private int red, blue, green;

    MyAlphaUpdateListener(ImageView[] ivs, int color) {
        imageViews = ivs;
        red = Color.red(color);
        green = Color.green(color);
        blue = Color.blue(color);
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Object o = animation.getAnimatedValue();
        int newalpha = (int) (255 * (float) o);
        int newColor = Color.argb(newalpha, red, green, blue);

        for (ImageView imageView : imageViews) {
            imageView.clearColorFilter();
            imageView.setColorFilter(newColor, PorterDuff.Mode.MULTIPLY);
        }

    }
}

As you can imagine, this will run quite often so I'd like to achieve a good performance. There seem to be no skipped frames but I also want to be as easy on the battery as possible. Is there anything I can do to reduce CPU time?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.