Search code examples
androidimageviewpositionzoomingscaletype

How to center imageView with matrix scaletype?


I'm using Android Studio to display an imageView. I'm using pinch zoom to interact with my ImageView.

Code:

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener{
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        scale = scale * detector.getScaleFactor();
        scale = Math.max(0.1f, Math.min(scale, 5f));
        matrix.setScale(scale, scale);

        imageView.setImageMatrix(matrix);
        return true;
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    scaleGestureDetector.onTouchEvent(event);
    return true;
}

Zoom is fine, but problem is the position of imageview, it's stuck in left upper corner. Tried layout changes but nothing to do. After some reseaches, I've seen these links in the forum ImageView Center in position with ScaleType Matrix and Center the image in ImageView after zoom-pinch, but these solutions aren't working, I've also checked the links given inside.

Help would be appreciated,

Thanks !

EDIT: Added the piece of code on how I get my ImageView

Picasso.with(this).load(url).resize(350, 330).centerInside().into(imageView);

onCreate Code

onCreate

ScaleListner Class and Gesture Code

listener


Solution

  •     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);