I'm trying to do an image viewer that when the user clicks on the image, the image is "cropped-out" and reveal the complete image.
For example in the screenshot below the user only see the part of the puppy initially. But after the user has clicked the image, the whole puppy is revealed. The image faded behind the first shows what the results of the animation would be.
Initially the ImageView is scaled to 50% in X and Y. And when the user clicks on the image the ImageView is scaled back to 100%, and the ImageView matrix is recalculated.
I tried all sort of way to calculate the matrix. But I cannot seem to find one that works with all type of crop and image: cropped landscape to portrait, cropped landscape to landscape, cropped portrait to portrait and cropped portrait to landscape. Is this even possible?
Here's my code right now. I'm trying to find what to put in setImageCrop()
.
public class MainActivity extends Activity {
private ImageView img;
private float translateCropX;
private float translateCropY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.img);
Drawable drawable = img.getDrawable();
translateCropX = -drawable.getIntrinsicWidth() / 2F;
translateCropY = -drawable.getIntrinsicHeight() / 2F;
img.setScaleX(0.5F);
img.setScaleY(0.5F);
img.setScaleType(ScaleType.MATRIX);
Matrix matrix = new Matrix();
matrix.postScale(2F, 2F); //zoom in 2X
matrix.postTranslate(translateCropX, translateCropY); //translate to the center of the image
img.setImageMatrix(matrix);
img.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final PropertyValuesHolder animScaleX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1F);
final PropertyValuesHolder animScaleY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1F);
final ObjectAnimator objectAnim = ObjectAnimator.ofPropertyValuesHolder(img, animScaleX, animScaleY);
final PropertyValuesHolder animMatrixCrop = PropertyValuesHolder.ofFloat("imageCrop", 0F, 1F);
final ObjectAnimator cropAnim = ObjectAnimator.ofPropertyValuesHolder(MainActivity.this, animMatrixCrop);
final AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(objectAnim).with(cropAnim);
animatorSet.start();
}
});
}
public void setImageCrop(float value) {
// No idea how to calculate the matrix depending on the scale
Matrix matrix = new Matrix();
matrix.postScale(2F, 2F);
matrix.postTranslate(translateCropX, translateCropY);
img.setImageMatrix(matrix);
}
}
Edit: It's worth mentioning that scaling the matrix linearly will not do. The ImageView is scaled linearly (0.5 to 1). But if I scale the Matrix linearly during the animation, the view is squish during the animation. The end result looks fine, but the image looks ugly during the animation.