2016-09-26 90 views
0

我有一個自定義工程圖視圖,它基本上在畫布上繪製位圖,然後使用填充算法在位圖上繪製。我正在嘗試實施縮放縮放功能。用戶放大後,我希望它們能夠在放大的位置繪製。這是我的onDraw(代碼):)安卓在縮放後在畫布上繪製位圖

protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    canvas.save(); 
    canvas.scale(mScaleFactor, mScaleFactor,mScaleX,mScaleY); 
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); 
    drawCanvas = new Canvas(canvasBitmap); 
    canvas.restore(); 
} 

的onTouchEvent(:

public boolean onTouchEvent(MotionEvent event) { 
//detect user touch 

    if(event.getPointerCount()>1) { 
     mScaleDetector.onTouchEvent(event); 
     invalidate(); 
     return true; 
    } 
    else { 
     float touchX = event.getX(); 
     float touchY = event.getY(); 
     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       //drawPath.moveTo(touchX, touchY); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       //drawPath.lineTo(touchX, touchY); 
       break; 
      case MotionEvent.ACTION_UP: 
       final Point p1 = new Point(); 
       float x0=touchX-mScaleX; 
       float y0=touchY-mScaleY; 
       x0=x0*mScaleFactor; 
       y0=y0*mScaleFactor; 
       x0+=mScaleX; 
       y0+=mScaleY; 
       p1.x = (int) x0; 
       p1.y = (int) y0; 
       Log.d("Pixel coordinates",p1.x+" "+p1.y); 
       Log.d("touch co-ordinates", touchX+" "+touchY); 
       Log.d("pivot points", mScaleX+" "+mScaleY); 
       Log.d("Scalefactor", Float.toString(mScaleFactor)); 
       int pixel = canvasBitmap.getPixel(p1.x, p1.y); 
       prev_bitmap = canvasBitmap.copy(Bitmap.Config.ARGB_8888, true); 
       bitMapStack.push(prev_bitmap); 
       floodFill(canvasBitmap, p1, pixel, paintColor); 
       break; 
      default: 
       return false; 

     } 
    } 
    invalidate(); 
    return true; 
} 

ScaleListener:

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 

     mScaleFactor *= detector.getScaleFactor(); 
     mScaleX=detector.getFocusX(); 
     mScaleY=detector.getFocusY(); 
     // Don't let the object get too small or too large. 
     mScaleFactor = Math.max(1f, Math.min(mScaleFactor, 5.0f)); 


     invalidate(); 
     return true; 
    } 
} 

每當我試着放大,我的應用程序失敗,我得到的消息:

致命例外:main 過程:com.example.dhruv.coloringbook,PID:14161 java.lang.IllegalArgumentException異常:y必須是< bitmap.height() 在android.graphics.Bitmap.checkPixelAccess(Bitmap.java:1429)

我不知道爲什麼會這樣,因爲getPixel甚至沒有應該在縮放手勢中被調用,而且我也不知道爲什麼我的y座標超出了位圖的範圍。我怎麼能解決這個問題/是否有更好的實現相同的東西?

編輯:全堆棧跟蹤: 09-25 16:44:48.456 16730-16730/com.example.dhruv.coloringbook d /像素座標:1080 2768 09-25 16:44:48.457 16730-16730/com.example.dhruv.coloringbook D/touch座標:106.0 724.0 09-25 16:44:48.457 16730-16730/com.example.dhruv.coloringbook D /支點:651.0 864.5 09-25 16:44 :48.457 16730-16730/com.example.dhruv.coloringbook D/Scalefactor:2.2871902 09-25 16:44:48.457 16730-16730/com.example.dhruv.coloringbook E/InputEventReceiver:異常調度輸入事件。 09-25 16:44:48.457 16730-16730/com.example.dhruv.coloringbook E/MessageQueue-JNI:MessageQueue回調中的異常:handleReceiveCallback 09-25 16:44:48.459 16730-16730/com.example.dhruv .coloringbook E/MessageQueue-JNI:java.lang.IllegalArgumentException:y必須是< bitmap.height() at android.graphics.Bitmap.checkPixelAccess(Bitmap.java:1429) at android.graphics.Bitmap.getPixel(Bitmap .java:1378) at com.example.dhruv.coloringbook.DrawingView.onTouchEvent(DrawingView.java:179) at android.view.View.dispatchTouchEvent(View.java:9297) at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android .view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) 在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) 在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) 在android.view .ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) 在android.view.android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) 。ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2555) 在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254) 在com.android.internal.policy.PhoneWindow $ DecorView.superDispatchTouchEvent(PhoneWindow.java:2403) 在com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737) at android.app.Activity.dispatchTouchEvent(Activity.java:2769) at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper。 java:60) at com.android.internal.policy.PhoneWindow $ DecorView.dispatchTouchEvent(PhoneWindow.java:2364) at android.view.View.dispatchPointerEvent(View.java:951 7) 在android.view.ViewRootImpl $ ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4242) 在android.view.ViewRootImpl $ ViewPostImeInputStage.onProcess(ViewRootImpl.java:4108) 在android.view.ViewRootImpl $ InputStage.deliver( ViewRootImpl.java:3654) at android.view.ViewRootImpl $ InputStage.onDeliverToNext(ViewRootImpl.java:3707) at android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3673) at android.view.ViewRootImpl $ AsyncInputStage.forward(ViewRootImpl.java:3799) at android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3681) at android.view.ViewRo otImpl $ AsyncInputStage.apply(ViewRootImpl.java:3856) 在android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java:3654) 在android.view.ViewRootImpl $ InputStage.onDeliverToNext(ViewRootImpl.java:3707) 在android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3673) at android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3681) at android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java: 3654) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5969) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5908) at android.v iew.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5869) 在android.view.ViewRootImpl $ WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6072) 在android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:192) 的機器人。 os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:323) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main (ActivityThread.java:5443) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java :728) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

+0

發佈完整的堆棧跟蹤,所以我們可以看到崩潰的邏輯流程。部分堆棧跟蹤不足以完全說明發生了什麼,特別是當它在框架代碼中崩潰時。 –

+0

編輯添加完整跟蹤 –

回答

0

所以,想象一下,你正在做一個捏放大。 YOu放下手指1.我們把它當作倒下。你放下手指2-現在我們看到兩個指針。我們離開了手指2.我們現在又有一個指針了。我們舉起手指1-我們得到了一個動作,但我們只看到一個指針(因爲另一個已經取消)。所以我們把它當作一個單一的手指。爲了防止這種情況發生,您需要跟蹤此觸摸中是否存在兩根手指。

這解釋了爲什麼getPixel在縮放中被調用。至於爲什麼崩潰 - 縮放的像素位置比畫布位圖大。解決上述問題可能會或可能不會解決它,因爲我不知道用什麼邏輯來調整/調整canvasBitmap的大小。

+0

感謝您對指針的建議!我會解決這個問題,然後再試一次。對於縮放位置,我使用了這篇文章的建議:http://stackoverflow.com/questions/29366418/after-canvas-zoom-with-pivot-point-x-and-y-coordinates-are-wrong? noredirect = 1&LQ = 1 –