Android image view matrix scale + translate
There's a convenient method called Matrix.setRectToRect(RectF, RectF, ScaleToFit) to help you here.
Matrix m = imageView.getImageMatrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
RectF viewRect = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
imageView.setImageMatrix(m);
That should set the matrix m
to have combo of scaling and translate values that is needed to show the drawable centered and fit within the ImageView widget.
Simultaneously scale and translate ImageView based on Target
I was able to achieve this animation by wrapping the target View in a layout group and animating them separately.
In other words, I translate the wrapper layout, and scale the child view. Translating and scaling the same view at the same time always seems to result in unexpected animation trajectories as the scaling messes with the coordinate system the translate animation is using.
translateTarget.animate().x(deltaX).y(deltaY).setDuration(1000);
scaleTarget.animate().scaleX(0.01f).scaleY(0.01f).setDuration(1000)
How to center imageView with matrix scaletype?
Picasso.with(this).load(url).into(imageView, new Callback.EmptyCallback() {
@Override
public void onSuccess() {
Drawable d = imageView.getDrawable();
// TODO: check that d isn't null
RectF imageRectF = new RectF(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
RectF viewRectF = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
matrix.setRectToRect(imageRectF, viewRectF, ScaleToFit.CENTER);
imageView.setImageMatrix(matrix);
}
});
Edit 2:
How to center the image like CENTER_INSIDE
but using matrix:
First we need a rectangle with the image dimensions:
Drawable d = imageView.getDrawable();
// TODO: check that d isn't null
RectF imageRectF = new RectF(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
Next you need a rectangle with the view dimensions:
RectF viewRectF = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
Now we run a method on matrix that will center the image in the view:
matrix.setRectToRect(imageRectF, viewRectF, ScaleToFit.CENTER);
What this does is set up the matrix so that the first rectangle will transform to the second rectangle. ScaleToFit.CENTER
will preserve the aspect ratio and have the same effect as scale type CENTER_INSIDE
.
So if you call
imageView.setImageMatrix(matrix);
at this point, you will have a centered image.
Edit: I think you are almost there.
Your matrix will undo the image centering that Picasso did, so you need to put in a translation to center the image before you scale it.
@Override
public boolean onScale(ScaleGestureDetector detector) {
Drawable d = imageView.getDrawable();
// if d is null, then Picasso hasn't loaded the image yet
float offsetX = (imageView.getWidth() - d.getIntrinsicWidth()) / 2F;
float offsetY = (imageView.getHeight() - d.getIntrinsicHeight()) / 2F;
float centerX = imageView.getWidth() / 2F;
float centerY = imageView.getHeight() / 2F;
// note that these offset and center values don't change with the scaling,
// so you can calculate them somewhere else and then use them here.
scale *= detector.getScaleFactor();
scale = Math.max(0.1f, Math.min(scale, 5f));
matrix.setScale(scale, scale, centerX, centerY);
matrix.preTranslate(offsetX, offsetY);
imageView.setImageMatrix(matrix);
}
You are using setScale(float sx, float sy)
. There is another version, setScale(float sx, float sy, float px, float py)
where px,py is a pivot point.
So if you want to center your image, determine the center of your view and use the x,y value as the pivot point.
You will also want to center the image inside the view, so you will need to move the image first before you scale.
float offsetX = (imageView.getWidth() - bitmap.getIntrinsicWidth()) / 2F;
float offsetY = (imageView.getHeight() - bitmap.getIntrinsicHeight()) / 2F;
float centerX = imageView.getWidth() / 2F;
float centerY = imageView.getHeight() / 2F;
matrix.setScale(scale, scale, centerX, centerY);
matrix.preTranslate(offsetX, offsetY);
Related Topics
Android 8.0: Java.Lang.Illegalstateexception: Not Allowed to Start Service Intent
Android Basics: Running Code in the Ui Thread
Can't Find Theme.Appcompat.Light For New Android Actionbar Support
The Application May Be Doing Too Much Work on Its Main Thread
How to Retrieve Data from Firebase to My Adapter
Android Studio: Add Jar as Library
How to Transfer Some Data to Another Fragment
How to Convert a Base64 String into a Bitmap Image to Show It in a Imageview
Getviewtypecount and Getitemviewtype Methods of Arrayadapter
Listview Inside Scrollview Is Not Scrolling on Android
Android Activity Life Cycle - What Are All These Methods For
How to Get a List of Installed Android Applications and Pick One to Run
Different Values Folders in Android
Android Studio - Google Map Still Blank on Real Android Device on Release Apk
Trying to Start a Service on Boot on Android
Android Marshmallow Request Permission
How to Stop Edittext from Gaining Focus When an Activity Starts in Android