简体   繁体   中英

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

I use the lib https://github.com/chrisbanes/PhotoView

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

How to scale and zoom 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

scale = 1f 在此处输入图片说明

scale = 4f and I want programly move center to x,y coordinates 在此处输入图片说明

I was facing the same issue, and finally made it.

So to achieve that I tried many things. First of all you need to convert your coordinates to the PhotoView :

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

Source : GitHub aslansari

This answer works for the zoom part. For the part of the programmatically movement of your object center to be on the screen center when zoomed in I made this.

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)

If you doesn't need the animation on the scale you doesn't need more.

If you want to use the animation

I figured the issue, but can't fix it yet. Here is my thoughts.

That doesn't work because it call the animation in another thread.

//PhotoViewAttacher.java
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.

I found a more simple solution. It is based on dispatchTouchEvent() method.

public class YourActivity extends AppCompatActivity {

    private float mTapX;
    private float mTapY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mTapX = ev.getX();
        mTapY = ev.getY();
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PhotoView photoView = findViewById(R.id.photo_view);
        mPhotoView.setImageResource(R.drawable.pic1);
        mPhotoView.setOnPhotoTapListener((view, x, y) -> {
            mPhotoView.setScale(photoView.getMaximumScale(), mTapX, mTapY, true);
        });
    }
}
    var photoView=findViewById(R.id.photoView)
    var zoomBtn=findViewById(R.id.zoomBtn)
    zoomBtn.setOnClickListener {
        if (photoView.scale!=photoView.minimumScale)
             photoView.scale = photoView.minimumScale
        else photoView.scale = photoView.maximumScale
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM