PhotoView icon indicating copy to clipboard operation
PhotoView copied to clipboard

How to scale (zoom and move) to x,y coordinates of Bitmap in PhotoVIew?

Open Kolyall opened this issue 7 years ago • 6 comments

At start I have Bitmap and x,y point on the Bitmap.

How to scale, zoom and move image to x,y coordinates of the bitmap?


    int bitmapWidth = bitmap.getWidth();//2418
    int bitmapHeight = bitmap.getHeight();//1889
    float x = 1209f;
    float y = 944f;

    float targetScale = 4f;    
    attacher.setScale(targetScale, x,y, false);//it doesnt work


Kolyall avatar Feb 24 '18 10:02 Kolyall

if this is not working for you try setting the scale AFTER the view renders:

Example:

    dashboard_image = (PhotoView) TheView.findViewById(R.id.dashboard_image);

    ViewTreeObserver vto = dashboard_image.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            dashboard_image.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            dashboard_image.setScale(2f);
        }
    });

tronious avatar Jul 18 '18 03:07 tronious

@tronious your code only works for scaling into center of the image, but what if (x,y) will be float x = 209f; float y = 444f;?

Kolyall avatar Jul 24 '18 06:07 Kolyall

@Kolyall try this, you need to calculate focal points

    int bitmapWidth = bitmap.getWidth();//2418
    int bitmapHeight = bitmap.getHeight();//1889
    float x = 1209f;
    float y = 944f;

    float focalX = x*photoView.getRight()/bitmap.getWidth();
    float focalY = y*photoView.getBottom()/bitmap.getHeight();

    float targetScale = 4f;    
    attacher.setScale(targetScale, focalX, focalY, false);

aslansari avatar Feb 15 '19 13:02 aslansari

@aslansari answer does the job, but it doesn't place the coordinates (focalX, focalY) to the center of the screen. It always keeps the image propotions like if the center is in the top left corner so the (focalX, focalY) will be in the top left corner of the zoomed image.

Does there is a method to change the zoom center to specific coordinates of the bitmap ?

EDIT : To achieve the simulating of the movement on the image to place my point to the center of screen, I created un MotionEvent but it failed.

val event = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis()+100, MotionEvent.ACTION_MOVE, focalX, focalY, 0)
mPhotoView.dispatchTouchEvent(event)

So I tried to trigger onDrag event but nothing happened.

mPhotoView.attacher.onDrag(focalX, focalY)

Did someone have more ideas on this ?

antoineFrau avatar Jul 22 '19 14:07 antoineFrau

Ok so I finally understand and make it work. That doesn't work because I used the animation on the setScale, which was call in an other thread.

mImageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));

And in the same time I tried to simulate the movement to re-center the point int the center of the screen.

var event = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, focalX, focalY, 0)
mPhotoView.dispatchTouchEvent(event)

val centerImageX = showResultCoinDetectionPhotoView.displayRect.centerX()
val centerImageY = showResultCoinDetectionPhotoView.displayRect.centerY()

var event = event = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, centerImageX, centerImageY, 0)
mPhotoView.dispatchTouchEvent(event)

But when this part of the code get executed the scale isn't finished, so the movement can't happened cause the image is full sized and we can't drag a full size image.

So to resolve that I remove the animation.

mPhotoView.setScale(5f, focalX, focalY, false)

An other solution could be use a callback or coroutine for the scaling and in the same time do the move, cause we will be in a sequential code part. But the AnimatedZoomRunnable is in another thread so we will go till the :

if (animate) {
       mImageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));
}

And go back to the next line of the coroutine.

So actually I don't have more option to do that. Maybe place a button to be able to center the point in the middle of the screen like in GoogleMap and execute the "simulating drag" when user click ?

Or does there is a way to get notify when AnimatedZoomRunnable is finished ?

Let me know if you found something interesting. Thanks.

antoineFrau avatar Jul 23 '19 13:07 antoineFrau

Ok so I finally understand and make it work. That doesn't work because I used the animation on the setScale, which was call in an other thread.

mImageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));

And in the same time I tried to simulate the movement to re-center the point int the center of the screen.

var event = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, focalX, focalY, 0)
mPhotoView.dispatchTouchEvent(event)

val centerImageX = showResultCoinDetectionPhotoView.displayRect.centerX()
val centerImageY = showResultCoinDetectionPhotoView.displayRect.centerY()

var event = event = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, centerImageX, centerImageY, 0)
mPhotoView.dispatchTouchEvent(event)

But when this part of the code get executed the scale isn't finished, so the movement can't happened cause the image is full sized and we can't drag a full size image.

So to resolve that I remove the animation.

mPhotoView.setScale(5f, focalX, focalY, false)

An other solution could be use a callback or coroutine for the scaling and in the same time do the move, cause we will be in a sequential code part. But the AnimatedZoomRunnable is in another thread so we will go till the :

if (animate) {
       mImageView.post(new AnimatedZoomRunnable(getScale(), scale, focalX, focalY));
}

And go back to the next line of the coroutine.

So actually I don't have more option to do that. Maybe place a button to be able to center the point in the middle of the screen like in GoogleMap and execute the "simulating drag" when user click ?

Or does there is a way to get notify when AnimatedZoomRunnable is finished ?

Let me know if you found something interesting. Thanks.

Hi. I am starting using PhotoView but cannot scale at a point I want. Can you review my problem in this post: https://stackoverflow.com/questions/77557191/cannot-scale-photoview-with-specific-position-in-image-resource

antoo05-11 avatar Dec 03 '23 17:12 antoo05-11