Android Pinch Zoom

How to pinch zoom on Android emulator?

Since ADT 17, it is possible to use a physical Android 4.0 device to send multitouch gestures to the emulator.See Android's instructions here.

Multi-Touch

The emulator supports multi-touch input, as an experimental feature in r17, using a tethered Android device running the SdkControllerMultitouch application. The application contains an activity that monitors touch inputs and sends them to the emulator. This requires an Android 4.0 or later system image.
The activity displays the content of the emulator screens to help with interactivity. It is recommended to enable "show touches" in the Developer section of the Settings on the emulator to see exactly where the touches are sent.

The SdkControllerSensor application source code is located in

$SDK/tools/apps/SdkControllerMultitouch/

But this is still a workaround since we need a real device. My advice would be to test your app directly on a real device as it's more robust, and even more performant.

android pinch zoom

Updated Answer

Code can be found here : official-doc

Answer Outdated

Check out the following links which may help you

Best examples are provided in the below links, which you can refactor to meet your requirements.

  1. Implementing the pinch zoom gesture

  2. Android-pinch

  3. GestureDetector.SimpleOnGestureListener

How to get if pinch zoom in is performed or pinch zoom out in android

As pskink recommended, you need ScaleGestureDetector object, which determines zoom "direction". Something like that:

ScaleGestureDetector mScaleDetector = new ScaleGestureDetector(getContext(),
new ScaleGestureDetector.SimpleOnScaleGestureListener() {

private float scaleFactor = 1f;

@Override
public boolean onScale(ScaleGestureDetector detector) {
// store scale factor for detect zoom "direction" on end
scaleFactor = detector.getScaleFactor();
return true;
}

@Override
public void onScaleEnd(ScaleGestureDetector detector) {
float currentZoom = mGoogleMap.getCameraPosition().zoom;
if (scaleFactor > 1) {
// zoom in detected
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mZoomCenter, currentZoom + 1));
} else if (scaleFactor < 1) {
// zoom out detected
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mZoomCenter, currentZoom - 1));
}
super.onScaleEnd(detector);
}
});

And you can use it in your EnhanchedMapView.dispatchTouchEvent() easily:

...
@Override
public boolean dispatchTouchEvent(MotionEvent event) {

// just call .onTouchEvent() on your ScaleGestureDetector object
mScaleDetector.onTouchEvent(event);

switch (event.getAction() & MotionEvent.ACTION_MASK) {
...

NB! You need to disable GoogleMap zoom gesture

@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.getUiSettings().setZoomGesturesEnabled(false);
...
}

and never enable it.

How to fix pinch zoom focal point in a custom view?

Using Matrix is a really better idea - the code is much more simple and you dont have to prove your math skills ;-), see how Matrix#postTranslate and Matrix#postScale methods are used:

class MyView extends View {
private static final String TAG = "MyView";

private final ScaleGestureDetector mScaleDetector;
private final GestureDetector mGestureDetector;

private final Drawable mBoard;
private final float mBoardWidth;
private final float mBoardHeight;
private Matrix mMatrix;

public MyView(Context context) {
this(context, null, 0);
}

public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

mBoard = ResourcesCompat.getDrawable(context.getResources(), R.drawable.chrome, null);
mBoardWidth = mBoard.getIntrinsicWidth();
mBoardHeight = mBoard.getIntrinsicHeight();
mBoard.setBounds(0, 0, (int) mBoardWidth, (int) mBoardHeight);

mMatrix = new Matrix();

mScaleDetector = new ScaleGestureDetector(context, scaleListener);
mGestureDetector = new GestureDetector(context, listener);
}

ScaleGestureDetector.OnScaleGestureListener scaleListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
float factor = scaleDetector.getScaleFactor();
mMatrix.postScale(factor, factor, getWidth() / 2f, getHeight() / 2f);
ViewCompat.postInvalidateOnAnimation(MyView.this);
return true;
}
};

GestureDetector.OnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dX, float dY) {
mMatrix.postTranslate(-dX, -dY);
ViewCompat.postInvalidateOnAnimation(MyView.this);
return true;
}
};

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
float scale = Math.max(w / mBoardWidth, h / mBoardHeight);
mMatrix.setScale(scale, scale);
mMatrix.postTranslate((w - scale * mBoardWidth) / 2f, (h - scale * mBoardHeight) / 2f);
}

@Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.concat(mMatrix);
mBoard.draw(canvas);
canvas.restore();
}

@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouchEvent(MotionEvent e) {
mGestureDetector.onTouchEvent(e);
mScaleDetector.onTouchEvent(e);
return true;
}
}

How to pinch zoom within finger point?

EDIT: Forked the original gist and updated it, view it here. It was a little more complex than I thought. The default pivot point for scaling a view is the center of the view. In order to make this work I had to set the view pivot to (0,0) and the adjust the translation for the pivot from the user's gesture.


I noticed in your onScale() override you are calling scaleDetector.getScaleFactor() but you are not calling scaleDetector.getFocusX() and scaleDetector.getFocusy(). These methods tell you what the focal point of the pinch-zoom is. You will have to call these methods and get this focal point (x,y) then do some calculations to figure out the translation required to keep that focal point. You will have to work this into your dx and dy values so that the translation accounts for the focal point.

To calculate the translation, you would take the focal point and multiply the x and y values by the change in scale factor. This tells you how far the point would move given focal point (0,0). So you would subtract x(updated) from x(original) and y(updated) from y(original) to get that move vector. Your translation values are the negated vector values. So:

scale(delta) = scaleDector.getScaleFactor() -- just the change, not the new scale factor
translation x = x(focal) - x(focal) * scale(delta)
translation y = y(focal) - y(focal) * scale(delta)

So obviously you would add these values to your dx and dy values for translation.

Pinch Zoom and 2 finger Rotation the ImageView in Android

Here is the solution that worked good for me. https://stackoverflow.com/a/18276033 Only one line I should add here and that should be


  1. add imageView.setRotation(imageView.getRotation() + (-angle)); in OnRotation(RotationGestureDetector rotationDetector) method inside the activity to set the new rotation value to the ImageView

This is for basic help. Remaining of the implementation is just fine



Related Topics



Leave a reply



Submit