Note that there are some explanatory texts on larger screens.

plurals
  1. POCanvas Pinch-Zoom to Point Within Bounds
    primarykey
    data
    text
    <p>I've been stuck on this problem for eight hours, so I figured it was time to get some help.</p> <p>Before I begin my problem, I'll just let it be known that I've been through this site and Google, and none of the answers I've found have helped. (<a href="https://stackoverflow.com/questions/8848523/canvas-zoom-goes-to-point-0-0">This</a> is one, <a href="https://stackoverflow.com/questions/6835224/android-bitmap-canvas-offset-after-scale">another</a>, and <a href="https://stackoverflow.com/questions/6624103/scaling-image-of-imageview-while-maintaining-center-point-in-same-place">another</a>.)</p> <p>Here's the deal: I have a class that extends <code>SurfaceView</code> (let's call it <code>MySurface</code>) and overrides many methods in it. Normally, it draws several squares and text boxes, which is all fine. As soon as a user starts touching, it converts to a <code>Bitmap</code>, then draws each frame that until the user releases.</p> <p>Here's the rub: I want to implement such a functionality that the user can place two fingers on the screen, pinch to zoom, and also pan around (but ONLY with two fingers down).</p> <p>I found a few implementations of pinch-to-zoom and adapted them to my <code>Canvas</code> object in <code>MySurface</code> via the following:</p> <pre><code>public void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.scale(mScaleVector.z, mScaleVector.z); // This is the scale factor as seen below canvas.translate(mScaleVector.x, mScaleVector.y); // These are offset values from 0,0, both working fine // Start draw code // ... // End draw code canvas.restore(); } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { float factor = detector.getScaleFactor(); if (Math.abs(factor - 1.0f) &gt;= 0.0075f) { mScaleVector.z *= factor; mScaleVector.z = Math.max(MIN_ZOOM, Math.min(mScaleVector.z, MAX_ZOOM)); } // ... invalidate(); return true; } } public boolean onTouchEvent(MotionEvent event) { int action = event.getAction() &amp; MotionEvent.ACTION_MASK; int pointerIndex = (event.getAction() &amp; MotionEvent.ACTION_POINTER_INDEX_MASK) &gt;&gt; MotionEvent.ACTION_POINTER_INDEX_SHIFT; if (event.getPointerCount() == 2) { if (action == MotionEvent.ACTION_POINTER_DOWN &amp;&amp; pointerIndex == 1) { // The various pivot coordinate codes would belong here } } detector.onTouchEvent(event); // Calls the Scale Gesture Detector return true; } </code></pre> <p>While both elements work fine--the scrolling back and forth and the pinch-to-zoom--there is one large problem. The pinch-to-zoom, when used, zooms into the point <code>0,0</code>, instead of zooming into the finger point.</p> <p>I've tried a lot of ways to fix this:</p> <ul> <li>Using <code>canvas.scale(mScaleVector.z, mScaleVector.z, mScaleVector.x, mScaleVector.y);</code>; obviously, this produces unwanted results as the <code>mScaleVector</code> x and y values are 0-offsets.</li> <li>Managing a "pivot" coordinate that uses the same offset as the <code>translate()</code> method, but this produces either the same <code>0,0</code> issue, or jumping around when the view is touched.</li> <li>Numerous other things... I've done a lot with the aforementioned pivot coordinate, trying to base its location on the user's first touch, and moving it relative to that touch each successive gesture.</li> </ul> <p>Additionally, this canvas must be bounded, so the user cannot scroll forever. However, when I use the <code>.scale(sx, sy, px, py)</code> method, it pushes things beyond any bounds I set in <code>.translate()</code>.</p> <p>I'm... pretty much open to anything at this point. I know this functionality can be added, as it is seen in the Android 4.0 gallery (when viewing a single image). I've tried to track down the source code that handles this, to no avail.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload