I\'m attempting to put an ImageView
in a CollapsingToolbarLayout
in which it takes up the full screen on load and as you scroll the content, the 16x9 r
You can achieve what you want by tracking vertical offset of AppBarLayout
. It has beautiful method addOnOffsetChangedListener
, so you can scale your image depending on offset of AppBarLayout
.
So, there are three things that you have to do to get it working:
drawable-nodpi
folder, to prevent Android from scaling it for different screen sizes.ImageView
's property scaleType
to matrix
- it's needed as we will change matrix of this ImageView
by ourselves.Implement addOnOffsetChangedListener
for you AppBarLayout
by next way:
final ImageView imageView = (ImageView) findViewById(R.id.img_hero);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.app_bar);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
Matrix matrix = new Matrix(imageView.getImageMatrix());
//get image's width and height
final int dwidth = imageView.getDrawable().getIntrinsicWidth();
final int dheight = imageView.getDrawable().getIntrinsicHeight();
//get view's width and height
final int vwidth = imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight();
int vheight = imageView.getHeight() - imageView.getPaddingTop() - imageView.getPaddingBottom();
float scale;
float dx = 0, dy = 0;
float parallaxMultiplier = ((CollapsingToolbarLayout.LayoutParams) imageView.getLayoutParams()).getParallaxMultiplier();
//maintain the image's aspect ratio depending on offset
if (dwidth * vheight > vwidth * dheight) {
vheight += (verticalOffset); //calculate view height depending on offset
scale = (float) vheight / (float) dheight; //calculate scale
dx = (vwidth - dwidth * scale) * 0.5f; //calculate x value of the center point of scaled drawable
dy = -verticalOffset * (1 - parallaxMultiplier); //calculate y value by compensating parallaxMultiplier
} else {
scale = (float) vwidth / (float) dwidth;
dy = (vheight - dheight * scale) * 0.5f;
}
int currentWidth = Math.round(scale * dwidth); //calculate current intrinsic width of the drawable
if (vwidth <= currentWidth) { //compare view width and drawable width to decide, should we scale more or not
matrix.setScale(scale, scale);
matrix.postTranslate(Math.round(dx), Math.round(dy));
imageView.setImageMatrix(matrix);
}
}
});
What I did here is just get ImageView
's source code to determine bounds when it has centerCrop
scale type and then just calculate the scale and translation of matrix depending on verticalOffset
. If scale value is less than 1.0f then we've just reached the point where our view's aspect ratio is equal to the drawable's aspect ratio, and we don't need to scale more.
Note:
centerCrop
parallaxMultiplier
is in between 0 and 1.How it looks for me: