In my project, I would like to animate a background with a large image pattern indefinitely like this:
I thought initially use a Matrix (for scale and translate) with a ValueAnimator to create the translation animation but I have no idea how to repeat the pattern.
What is the way to develop this effect? Thank you for your help.
Update, my source code without repeat (Note: In the GIF animation I drew the image pattern horizontally for representation simplicities but I need a vertically translation animation in reality):
background.setImageResource(R.drawable.background);
background.setScaleType(ScaleType.MATRIX);
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private Matrix matrix = new Matrix();
@Override public void onAnimationUpdate(ValueAnimator animation) {
float factor = (Float) animation.getAnimatedValue();
int width = background.getDrawable().getIntrinsicWidth();
int height = background.getDrawable().getIntrinsicHeight();
float scale = (float) background.getWidth() / (float) width;
matrix.reset();
matrix.postTranslate(0, -height * factor);
matrix.postScale(scale, scale);
background.setImageMatrix(matrix);
}
});
animator.setInterpolator(new LinearInterpolator());
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setDuration(10000);
animator.start();
I finally extends BitmapDrawable to override the draw() method:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.background);
BitmapDrawable drawable = new BitmapDrawable(getResources(), bitmap) {
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawBitmap(getBitmap(), 0, getIntrinsicHeight(), null);
}
};
background.setImageDrawable(drawable);
background.setScaleType(ScaleType.MATRIX);
ValueAnimator animator = ValueAnimator.ofFloat(0);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private Matrix matrix = new Matrix();
@Override
public void onAnimationUpdate(ValueAnimator animator) {
matrix.reset();
int height = background.getDrawable().getIntrinsicHeight();
float translate = -height * animator.getAnimatedFraction();
matrix.postTranslate(0, translate);
float width = background.getDrawable().getIntrinsicWidth();
float scale = background.getWidth() / width;
matrix.postScale(scale, scale);
background.setImageMatrix(matrix);
}
});
animator.setInterpolator(new LinearInterpolator());
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setDuration(10000);
animator.start();
Note: drawable.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT)
does not works with imageView.setScaleType(ScaleType.MATRIX)
.
So I don't know if it is a good practice but it is the only one I found for the moment. If you have any idea to improve the technique, please share it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With