Skip to content

Instantly share code, notes, and snippets.

@rudchenkos
Created July 14, 2017 12:47
Show Gist options
  • Save rudchenkos/e33dc0d6669a61dde9d6548f6c3e0e7e to your computer and use it in GitHub Desktop.
Save rudchenkos/e33dc0d6669a61dde9d6548f6c3e0e7e to your computer and use it in GitHub Desktop.
Maintain aspect ratio of bitmap drawables set as windowBackground on Android
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/**
* Drawable decorator which draws the target drawable similarly to an ImageView with scaleType=centerCrop
*
* Example usage:
* final Drawable bg = getResources().getDrawable(R.drawable.screen);
* getWindow().setBackgroundDrawable(new CenterCropDrawable(bg));
*/
public class CenterCropDrawable extends Drawable {
@NonNull
private final Drawable target;
public CenterCropDrawable(@NonNull Drawable target) {
this.target = target;
}
@Override
public void setBounds(@NonNull Rect bounds) {
super.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
final RectF sourceRect = new RectF(0, 0, target.getIntrinsicWidth(), target.getIntrinsicHeight());
final RectF screenRect = new RectF(left, top, right, bottom);
final Matrix matrix = new Matrix();
matrix.setRectToRect(screenRect, sourceRect, Matrix.ScaleToFit.CENTER);
final Matrix inverse = new Matrix();
matrix.invert(inverse);
inverse.mapRect(sourceRect);
target.setBounds(Math.round(sourceRect.left), Math.round(sourceRect.top),
Math.round(sourceRect.right), Math.round(sourceRect.bottom));
super.setBounds(left, top, right, bottom);
}
@Override
public void draw(@NonNull Canvas canvas) {
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(getBounds());
target.draw(canvas);
canvas.restore();
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
target.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
target.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return target.getOpacity();
}
}
@CrandellWS
Copy link

Great work thanks! ...

you might update
Canvas.CLIP_SAVE_FLAG to Canvas.ALL_SAVE_FLAG

@pedroRelvas
Copy link

Hi. Can someone explain the code? This resolved my problem...but I can't get it. Thank you.

@rudchenkos
Copy link
Author

rudchenkos commented Aug 26, 2019

Hey @CrandellWS
Why do you think we should use theCanvas.ALL_SAVE_FLAG?
As I see it, I only change clip rectangle so this is the only thing I need to save and restore. This should be significantly cheaper than saving/restoring the entire Canvas state.

Sorry for the late reply :)

@pchell
Copy link

pchell commented Jun 5, 2020

Hi) Great solution, but on some devices does enamation freeze? What could be the problem ?

Here in this version, it freeze on some devices:
animationBackground = (AnimatedVectorDrawable) getDrawable(R.drawable.splash_screen_anim); getWindow().setBackgroundDrawable(new CenterCropDrawable(animationBackground));

But, if you changed the code and remove new CenterCropDrawable, then the animation stops freezing on these devices:
animationBackground = (AnimatedVectorDrawable) getDrawable(R.drawable.splash_screen_anim); getWindow().setBackgroundDrawable(animationBackground);

@rudchenkos
Copy link
Author

Hi @pchell

What is your animation? Could it be that CenterCropDrawable overrides every frame of your animanation by, well, centering the drawable?

@pchell
Copy link

pchell commented Jun 9, 2020

Hi @rudchenkos !
I use animated-vector. I created a question on https://stackoverflow.com/questions/62166507/setanimatedvectordrawable-start-does-not-work-on-some-devices. I would be very grateful if you could help resolve the issue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment