List of usage examples for android.graphics PointF PointF
public PointF(float x, float y)
From source file:com.bizcom.vc.widget.cus.SubsamplingScaleImageView.java
/** * Handle touch events. One finger pans, and two finger pinch and zoom plus * panning./*from w w w . j a v a 2 s . c o m*/ */ @Override public boolean onTouchEvent(MotionEvent event) { PointF vCenterEnd; float vDistEnd; // During non-interruptible anims, ignore all touch events if (anim != null && !anim.interruptible) { getParent().requestDisallowInterceptTouchEvent(true); return true; } else { anim = null; } // Abort if not ready if (vTranslate == null) { return true; } // Detect flings, taps and double taps if (detector == null || detector.onTouchEvent(event)) { return true; } int touchCount = event.getPointerCount(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_1_DOWN: case MotionEvent.ACTION_POINTER_2_DOWN: anim = null; getParent().requestDisallowInterceptTouchEvent(true); maxTouchCount = Math.max(maxTouchCount, touchCount); if (touchCount >= 2) { if (zoomEnabled) { // Start pinch to zoom. Calculate distance between touch // points and center point of the pinch. float distance = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1)); scaleStart = scale; vDistStart = distance; vTranslateStart = new PointF(vTranslate.x, vTranslate.y); vCenterStart = new PointF((event.getX(0) + event.getX(1)) / 2, (event.getY(0) + event.getY(1)) / 2); } else { // Abort all gestures on second touch maxTouchCount = 0; } // Cancel long click timer handler.removeMessages(MESSAGE_LONG_CLICK); } else { // Start one-finger pan vTranslateStart = new PointF(vTranslate.x, vTranslate.y); vCenterStart = new PointF(event.getX(), event.getY()); // Start long click timer handler.sendEmptyMessageDelayed(MESSAGE_LONG_CLICK, 600); } return true; case MotionEvent.ACTION_MOVE: boolean consumed = false; if (maxTouchCount > 0) { if (touchCount >= 2) { // Calculate new distance between touch points, to scale and // pan relative to start values. vDistEnd = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1)); vCenterEnd = new PointF((event.getX(0) + event.getX(1)) / 2, (event.getY(0) + event.getY(1)) / 2); if (zoomEnabled && (distance(vCenterStart.x, vCenterEnd.x, vCenterStart.y, vCenterEnd.y) > 5 || Math.abs(vDistEnd - vDistStart) > 5 || isPanning)) { isZooming = true; isPanning = true; consumed = true; scale = Math.min(maxScale, (vDistEnd / vDistStart) * scaleStart); if (scale <= minScale()) { // Minimum scale reached so don't pan. Adjust start // settings so any expand will zoom in. vDistStart = vDistEnd; scaleStart = minScale(); vCenterStart = vCenterEnd; vTranslateStart = vTranslate; } else if (panEnabled) { // Translate to place the source image coordinate // that was at the center of the pinch at the start // at the center of the pinch now, to give // simultaneous pan + zoom. float vLeftStart = vCenterStart.x - vTranslateStart.x; float vTopStart = vCenterStart.y - vTranslateStart.y; float vLeftNow = vLeftStart * (scale / scaleStart); float vTopNow = vTopStart * (scale / scaleStart); vTranslate.x = vCenterEnd.x - vLeftNow; vTranslate.y = vCenterEnd.y - vTopNow; } else if (sRequestedCenter != null) { // With a center specified from code, zoom around // that point. vTranslate.x = (getWidth() / 2) - (scale * sRequestedCenter.x); vTranslate.y = (getHeight() / 2) - (scale * sRequestedCenter.y); } else { // With no requested center, scale around the image // center. vTranslate.x = (getWidth() / 2) - (scale * (sWidth() / 2)); vTranslate.y = (getHeight() / 2) - (scale * (sHeight() / 2)); } fitToBounds(true); refreshRequiredTiles(false); } } else if (!isZooming) { // One finger pan - translate the image. We do this // calculation even with pan disabled so click // and long click behaviour is preserved. float dx = Math.abs(event.getX() - vCenterStart.x); float dy = Math.abs(event.getY() - vCenterStart.y); if (dx > 5 || dy > 5 || isPanning) { consumed = true; vTranslate.x = vTranslateStart.x + (event.getX() - vCenterStart.x); vTranslate.y = vTranslateStart.y + (event.getY() - vCenterStart.y); float lastX = vTranslate.x; float lastY = vTranslate.y; fitToBounds(true); if (lastX == vTranslate.x || (lastY == vTranslate.y && dy > 10) || isPanning) { isPanning = true; } else if (dx > 5) { // Haven't panned the image, and we're at the left // or right edge. Switch to page swipe. maxTouchCount = 0; handler.removeMessages(MESSAGE_LONG_CLICK); getParent().requestDisallowInterceptTouchEvent(false); } if (!panEnabled) { vTranslate.x = vTranslateStart.x; vTranslate.y = vTranslateStart.y; getParent().requestDisallowInterceptTouchEvent(false); } refreshRequiredTiles(false); } } } if (consumed) { handler.removeMessages(MESSAGE_LONG_CLICK); invalidate(); return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_2_UP: handler.removeMessages(MESSAGE_LONG_CLICK); if (maxTouchCount > 0 && (isZooming || isPanning)) { if (isZooming && touchCount == 2) { // Convert from zoom to pan with remaining touch isPanning = true; vTranslateStart = new PointF(vTranslate.x, vTranslate.y); if (event.getActionIndex() == 1) { vCenterStart = new PointF(event.getX(0), event.getY(0)); } else { vCenterStart = new PointF(event.getX(1), event.getY(1)); } } if (touchCount < 3) { // End zooming when only one touch point isZooming = false; } if (touchCount < 2) { // End panning when no touch points isPanning = false; maxTouchCount = 0; } // Trigger load of tiles now required refreshRequiredTiles(true); return true; } if (touchCount == 1) { isZooming = false; isPanning = false; maxTouchCount = 0; } return true; } return super.onTouchEvent(event); }
From source file:me.ccrama.redditslide.Views.SubsamplingScaleImageView.java
private void setGestureDetector(final Context context) { this.detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override//from ww w.j a v a 2 s . c o m public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (panEnabled && readySent && vTranslate != null && e1 != null && e2 != null && (Math.abs(e1.getX() - e2.getX()) > 50 || Math.abs(e1.getY() - e2.getY()) > 50) && (Math.abs(velocityX) > 500 || Math.abs(velocityY) > 500) && !isZooming) { PointF vTranslateEnd = new PointF(vTranslate.x + (velocityX * 0.25f), vTranslate.y + (velocityY * 0.25f)); float sCenterXEnd = ((getWidth() / 2) - vTranslateEnd.x) / scale; float sCenterYEnd = ((getHeight() / 2) - vTranslateEnd.y) / scale; new AnimationBuilder(new PointF(sCenterXEnd, sCenterYEnd)).withEasing(EASE_OUT_QUAD) .withPanLimited(false).start(); return true; } return super.onFling(e1, e2, velocityX, velocityY); } @Override public boolean onSingleTapConfirmed(MotionEvent e) { performClick(); return true; } @Override public boolean onDoubleTap(MotionEvent e) { if (zoomEnabled && readySent && vTranslate != null) { // Hacky solution for #15 - after a double tap the GestureDetector gets in a state // where the next fling is ignored, so here we replace it with a new one. setGestureDetector(context); if (quickScaleEnabled) { // Store quick scale params. This will become either a double tap zoom or a // quick scale depending on whether the user swipes. vCenterStart = new PointF(e.getX(), e.getY()); vTranslateStart = new PointF(vTranslate.x, vTranslate.y); scaleStart = scale; isQuickScaling = true; isZooming = true; quickScaleCenter = viewToSourceCoord(vCenterStart); quickScaleLastDistance = -1F; quickScaleLastPoint = new PointF(quickScaleCenter.x, quickScaleCenter.y); quickScaleMoved = false; // We need to get events in onTouchEvent after this. return false; } else { // Start double tap zoom animation. doubleTapZoom(viewToSourceCoord(new PointF(e.getX(), e.getY())), new PointF(e.getX(), e.getY())); return true; } } return super.onDoubleTapEvent(e); } }); }
From source file:ac.robinson.paperchains.PaperChainsActivity.java
public void audioSaveCompleted(final Rect audioRect, final long trackId) { // convert back to grid-based coordinates final PointF rectLeftTop = QRImageParser.getGridPosition(mImageParameters, new PointF(audioRect.left, audioRect.top)); final PointF rectRightBottom = QRImageParser.getGridPosition(mImageParameters, new PointF(audioRect.right, audioRect.bottom)); // account for image rotation/inversion by making sure to use the min/max values of each coordinate int left = Math.round(rectLeftTop.x); int top = Math.round(rectLeftTop.y); int right = Math.round(rectRightBottom.x); int bottom = Math.round(rectRightBottom.y); final int leftmost = Math.min(left, right); final int topmost = Math.min(top, bottom); final int rightmost = Math.max(left, right); final int bottommost = Math.max(top, bottom); RequestParams params = new RequestParams("newaudio", 1); // 1 reserved for possible future use as box ID params.put("left", leftmost); params.put("top", topmost); params.put("right", rightmost); params.put("bottom", bottommost); params.put("soundCloudId", trackId); params.put("pageId", mPageId); // update on the server new AsyncHttpClient().get(CODE_SERVER_URL, params, new JsonHttpResponseHandler() { @Override// ww w.jav a 2 s . c om public void onSuccess(int statusCode, Header[] headers, JSONObject response) { try { if ("ok".equals(response.getString("status"))) { AudioAreaHolder holder = new AudioAreaHolder(trackId, new Rect(leftmost, topmost, rightmost, bottommost)); holder.setImageRect(new Rect(audioRect)); mAudioAreas.add(holder); mImageView.addAudioAreaRect(holder.imageRect); mSaveButton.clearAnimation(); mSaveButton.setImageResource(R.drawable.ic_done_white_24dp); delayedResetRecordingInterface(); } else { audioSaveFailed(R.string.hint_audio_save_failed); } } catch (JSONException e) { audioSaveFailed(R.string.hint_audio_save_failed); } } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) { audioSaveFailed(R.string.hint_audio_save_failed); } }); }
From source file:com.zenithed.core.widget.scaledimageview.ScaledImageView.java
private void scaleToHelper(float sx, float sy, float newScale, int duration) { if (newScale > mMaxScale) newScale = mMaxScale;//from w w w.ja v a 2 s. c o m if (newScale == mScale) return; // if the image is not ready we can't zoom. if (mScale <= 0) return; mScroller.forceFinished(true); mZoomerInitialScale = mScale; mZoomerInitialDestinationPoint = new PointF(sx, sy); mZoomer.startZoom(mScale, newScale, duration); ViewCompat.postInvalidateOnAnimation(ScaledImageView.this); }
From source file:me.ccrama.redditslide.Views.SubsamplingScaleImageView.java
/** * Handle touch events. One finger pans, and two finger pinch and zoom plus panning. *///from www. j a v a 2s . co m @Override @SuppressWarnings("deprecation") public boolean onTouchEvent(@NonNull MotionEvent event) { // During non-interruptible anims, ignore all touch events if (anim != null && !anim.interruptible) { getParent().requestDisallowInterceptTouchEvent(true); return true; } else { if (anim != null && anim.listener != null) { try { anim.listener.onInterruptedByUser(); } catch (Exception e) { Log.w(TAG, "Error thrown by animation listener", e); } } anim = null; } // Abort if not ready if (vTranslate == null) { return true; } // Detect flings, taps and double taps if (!isQuickScaling && (detector == null || detector.onTouchEvent(event))) { isZooming = false; isPanning = false; maxTouchCount = 0; return true; } if (vTranslateStart == null) { vTranslateStart = new PointF(0, 0); } if (vCenterStart == null) { vCenterStart = new PointF(0, 0); } int touchCount = event.getPointerCount(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_1_DOWN: case MotionEvent.ACTION_POINTER_2_DOWN: anim = null; getParent().requestDisallowInterceptTouchEvent(true); maxTouchCount = Math.max(maxTouchCount, touchCount); if (touchCount >= 2) { if (zoomEnabled) { // Start pinch to zoom. Calculate distance between touch points and center point of the pinch. float distance = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1)); scaleStart = scale; vDistStart = distance; vTranslateStart.set(vTranslate.x, vTranslate.y); vCenterStart.set((event.getX(0) + event.getX(1)) / 2, (event.getY(0) + event.getY(1)) / 2); } else { // Abort all gestures on second touch maxTouchCount = 0; } // Cancel long click timer handler.removeMessages(MESSAGE_LONG_CLICK); } else if (!isQuickScaling) { // Start one-finger pan vTranslateStart.set(vTranslate.x, vTranslate.y); vCenterStart.set(event.getX(), event.getY()); // Start long click timer handler.sendEmptyMessageDelayed(MESSAGE_LONG_CLICK, 600); } return true; case MotionEvent.ACTION_MOVE: boolean consumed = false; if (maxTouchCount > 0) { if (touchCount >= 2) { // Calculate new distance between touch points, to scale and pan relative to start values. float vDistEnd = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1)); float vCenterEndX = (event.getX(0) + event.getX(1)) / 2; float vCenterEndY = (event.getY(0) + event.getY(1)) / 2; if (zoomEnabled && (distance(vCenterStart.x, vCenterEndX, vCenterStart.y, vCenterEndY) > 5 || Math.abs(vDistEnd - vDistStart) > 5 || isPanning)) { isZooming = true; isPanning = true; consumed = true; setScale(Math.min(maxScale, (vDistEnd / vDistStart) * scaleStart)); if (scale <= minScale()) { // Minimum scale reached so don't pan. Adjust start settings so any expand will zoom in. vDistStart = vDistEnd; scaleStart = minScale(); vCenterStart.set(vCenterEndX, vCenterEndY); vTranslateStart.set(vTranslate); } else if (panEnabled) { // Translate to place the source image coordinate that was at the center of the pinch at the start // at the center of the pinch now, to give simultaneous pan + zoom. float vLeftStart = vCenterStart.x - vTranslateStart.x; float vTopStart = vCenterStart.y - vTranslateStart.y; float vLeftNow = vLeftStart * (scale / scaleStart); float vTopNow = vTopStart * (scale / scaleStart); vTranslate.x = vCenterEndX - vLeftNow; vTranslate.y = vCenterEndY - vTopNow; } else if (sRequestedCenter != null) { // With a center specified from code, zoom around that point. vTranslate.x = (getWidth() / 2) - (scale * sRequestedCenter.x); vTranslate.y = (getHeight() / 2) - (scale * sRequestedCenter.y); } else { // With no requested center, scale around the image center. vTranslate.x = (getWidth() / 2) - (scale * (sWidth() / 2)); vTranslate.y = (getHeight() / 2) - (scale * (sHeight() / 2)); } fitToBounds(true); refreshRequiredTiles(false); } } else if (isQuickScaling) { // One finger zoom // Stole Google's Magical Formula to make sure it feels the exact same float dist = Math.abs(vCenterStart.y - event.getY()) * 2 + quickScaleThreshold; if (quickScaleLastDistance == -1F) quickScaleLastDistance = dist; boolean isUpwards = event.getY() > quickScaleLastPoint.y; quickScaleLastPoint.set(0, event.getY()); float spanDiff = (Math.abs(1 - (dist / quickScaleLastDistance)) * 0.5F); if (spanDiff > 0.03f || quickScaleMoved) { quickScaleMoved = true; float multiplier = 1; if (quickScaleLastDistance > 0) { multiplier = isUpwards ? (1 + spanDiff) : (1 - spanDiff); } setScale(Math.max(minScale(), Math.min(maxScale, scale * multiplier))); if (panEnabled) { float vLeftStart = vCenterStart.x - vTranslateStart.x; float vTopStart = vCenterStart.y - vTranslateStart.y; float vLeftNow = vLeftStart * (scale / scaleStart); float vTopNow = vTopStart * (scale / scaleStart); vTranslate.x = vCenterStart.x - vLeftNow; vTranslate.y = vCenterStart.y - vTopNow; } else if (sRequestedCenter != null) { // With a center specified from code, zoom around that point. vTranslate.x = (getWidth() / 2) - (scale * sRequestedCenter.x); vTranslate.y = (getHeight() / 2) - (scale * sRequestedCenter.y); } else { // With no requested center, scale around the image center. vTranslate.x = (getWidth() / 2) - (scale * (sWidth() / 2)); vTranslate.y = (getHeight() / 2) - (scale * (sHeight() / 2)); } } quickScaleLastDistance = dist; fitToBounds(true); refreshRequiredTiles(false); consumed = true; } else if (!isZooming) { // One finger pan - translate the image. We do this calculation even with pan disabled so click // and long click behaviour is preserved. float dx = Math.abs(event.getX() - vCenterStart.x); float dy = Math.abs(event.getY() - vCenterStart.y); if (dx > 5 || dy > 5 || isPanning) { consumed = true; vTranslate.x = vTranslateStart.x + (event.getX() - vCenterStart.x); vTranslate.y = vTranslateStart.y + (event.getY() - vCenterStart.y); float lastX = vTranslate.x; float lastY = vTranslate.y; fitToBounds(true); boolean atXEdge = lastX != vTranslate.x; boolean edgeXSwipe = atXEdge && dx > dy && !isPanning; boolean yPan = lastY == vTranslate.y && dy > 15; if (!edgeXSwipe && (!atXEdge || yPan || isPanning)) { isPanning = true; } else if (dx > 5) { // Haven't panned the image, and we're at the left or right edge. Switch to page swipe. maxTouchCount = 0; handler.removeMessages(MESSAGE_LONG_CLICK); getParent().requestDisallowInterceptTouchEvent(false); } if (!panEnabled) { vTranslate.x = vTranslateStart.x; vTranslate.y = vTranslateStart.y; getParent().requestDisallowInterceptTouchEvent(false); } refreshRequiredTiles(false); } } } if (consumed) { handler.removeMessages(MESSAGE_LONG_CLICK); invalidate(); return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_2_UP: handler.removeMessages(MESSAGE_LONG_CLICK); if (isQuickScaling) { isQuickScaling = false; if (!quickScaleMoved) { doubleTapZoom(quickScaleCenter, vCenterStart); } } if (maxTouchCount > 0 && (isZooming || isPanning)) { if (isZooming && touchCount == 2) { // Convert from zoom to pan with remaining touch isPanning = true; vTranslateStart.set(vTranslate.x, vTranslate.y); if (event.getActionIndex() == 1) { vCenterStart.set(event.getX(0), event.getY(0)); } else { vCenterStart.set(event.getX(1), event.getY(1)); } } if (touchCount < 3) { // End zooming when only one touch point isZooming = false; } if (touchCount < 2) { // End panning when no touch points isPanning = false; maxTouchCount = 0; } // Trigger load of tiles now required refreshRequiredTiles(true); return true; } if (touchCount == 1) { isZooming = false; isPanning = false; maxTouchCount = 0; } return true; } return super.onTouchEvent(event); }
From source file:com.zenithed.core.widget.scaledimageview.ScaledImageView.java
/** * Manages the scroller to scroll ahead the initial destination point with middling it between the focus point, * while the content's scale is changing.. * @param initialDestinationPoint the initial point from the content source to be focused on while zooming (the destination point when zooming ends). * @param focusPoint of the view to middle the destination's source point between it. * @param initialScale the original scale of the content before scaling, not the current mScale value. */// ww w .ja v a 2s. c o m private void zoomAndFocusOnPoint(PointF initialDestinationPoint, PointF focusPoint, float initialScale) { /* * Every point is related to the original selected on, the only differences * when moving with the scale motions is the tendency of drawing content scale - initialScale (original mScale). */ PointF currentPoint = new PointF((initialDestinationPoint.x) * (mScale / initialScale), (initialDestinationPoint.y) * (mScale / initialScale)); // gets the top and the left points of the viewport. final int pointX = (int) (currentPoint.x - focusPoint.x); final int pointY = (int) (currentPoint.y - focusPoint.y); mScroller.computeScrollOffset(); final int startX = mScroller.getCurrX(); final int startY = mScroller.getCurrY(); mScroller.startScroll(startX, startY, pointX - startX, pointY - startY, 0); fitToBounds(); refreshRequiredTiles(false); ViewCompat.postInvalidateOnAnimation(ScaledImageView.this); }
From source file:ac.robinson.paperchains.PaperChainsActivity.java
private void animateRecordingInterface(int direction, View keyView) { mPlayButton.setVisibility(View.VISIBLE); mDeleteButton.setVisibility(View.VISIBLE); mSaveButton.setVisibility(View.VISIBLE); // animate the control buttons out to be equally spaced around the record button float buttonOffset = -mPlayButton.getWidth(); PointF centre = new PointF(0, 0); PointF startingPoint = new PointF(0, buttonOffset); double radRot = Math.toRadians(-120); double cosRot = Math.cos(radRot); double sinRot = Math.sin(radRot); QRImageParser.rotatePoint(startingPoint, centre, cosRot, sinRot); float leftX = startingPoint.x; float leftY = startingPoint.y; QRImageParser.rotatePoint(startingPoint, centre, cosRot, sinRot); float rightX = startingPoint.x; float rightY = startingPoint.y; RelativeLayout parent;//from w w w .ja v a 2 s . c om AnimatorSet buttonAnimator = new AnimatorSet(); switch (direction) { case 1: // out // on an outward animation, we want the three minor buttons to have priority so the record button's // larger click area doesn't capture their clicks mPlayButton.bringToFront(); mDeleteButton.bringToFront(); mSaveButton.bringToFront(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { // need to manually re-layout before KitKat parent = (RelativeLayout) mPlayButton.getParent(); parent.requestLayout(); parent.invalidate(); } buttonAnimator.playTogether(ObjectAnimator.ofFloat(mDeleteButton, "translationX", 0, leftX), ObjectAnimator.ofFloat(mDeleteButton, "translationY", 0, leftY), ObjectAnimator.ofFloat(mSaveButton, "translationX", 0, rightX), ObjectAnimator.ofFloat(mSaveButton, "translationY", 0, rightY), ObjectAnimator.ofFloat(mPlayButton, "translationY", 0, buttonOffset)); buttonAnimator.setInterpolator(new OvershootInterpolator()); break; case -1: // in // keyView is the view we want to be at the front after an inward animation if (keyView != null) { keyView.bringToFront(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { // need to manually re-layout before KitKat parent = (RelativeLayout) keyView.getParent(); parent.requestLayout(); parent.invalidate(); } } buttonAnimator.playTogether(ObjectAnimator.ofFloat(mDeleteButton, "translationX", leftX, 0), ObjectAnimator.ofFloat(mDeleteButton, "translationY", leftY, 0), ObjectAnimator.ofFloat(mSaveButton, "translationX", rightX, 0), ObjectAnimator.ofFloat(mSaveButton, "translationY", rightY, 0), ObjectAnimator.ofFloat(mPlayButton, "translationY", buttonOffset, 0)); buttonAnimator.setInterpolator(new AnticipateInterpolator()); break; } buttonAnimator.setDuration(BUTTON_ANIMATION_DURATION); buttonAnimator.start(); }
From source file:com.zenithed.core.widget.scaledimageview.ScaledImageView.java
/** * Convert screen coordinate to source coordinate. *//*from w w w .jav a 2 s . com*/ public PointF viewToSourceCoord(float vx, float vy) { if (mTranslate == null) { return null; } float sx = (vx - mTranslate.x) / mScale; float sy = (vy - mTranslate.y) / mScale; return new PointF(sx, sy); }
From source file:com.zenithed.core.widget.scaledimageview.ScaledImageView.java
/** * Convert source coordinate to screen coordinate. *///from www . j a va 2s. c o m public PointF sourceToViewCoord(float sx, float sy) { float vx = (sx * mScale) + mTranslate.x; float vy = (sy * mScale) + mTranslate.y; return new PointF(vx, vy); }
From source file:com.mylikes.likes.etchasketch.Slate.java
@SuppressLint("NewApi") @Override/* ww w . jav a 2 s . com*/ public boolean onTouchEvent(MotionEvent event) { final int action = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) ? event.getActionMasked() : event.getAction(); int N = event.getHistorySize(); int P = event.getPointerCount(); long time = event.getEventTime(); mEmpty = false; // starting a new touch? commit the previous state of the canvas if (action == MotionEvent.ACTION_DOWN) { commitStroke(); } if (mZoomMode) { return false; } int pointerIndex = MotionEventCompat.getActionIndex(event); int pointerId = event.getPointerId(pointerIndex); if (moveMode) { if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) { if (firstFinger != null) { MotionEvent.PointerCoords coords1 = new MotionEvent.PointerCoords(); event.getPointerCoords(0, coords1); Log.d(TAG, "coords1: " + coords1.x + " " + coords1.y); MotionEvent.PointerCoords coords2 = new MotionEvent.PointerCoords(); event.getPointerCoords(1, coords2); firstFinger.set(coords1.x, coords1.y); secondFinger = new PointF(coords2.x, coords2.y); } else { touchStartTime = System.currentTimeMillis(); moveDrawingStartX = event.getX(); moveDrawingStartY = event.getY(); int i = 0; moveDrawingIndex = -1; resizeDrawingIndex = -1; resizeDrawingCorner = null; if (selectedDrawing != null) { moveDrawingIndex = 0; } if (i >= overlays.size()) { return true; } Log.d(TAG, "Start dragging overlay"); firstFinger = new PointF(event.getX(), event.getY()); } return true; } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) { if (secondFinger != null) { secondFinger = null; MotionEvent.PointerCoords coords1 = new MotionEvent.PointerCoords(); event.getPointerCoords(0, coords1); moveDrawingStartX = coords1.x; moveDrawingStartY = coords1.y; return true; } if (firstFinger != null) { firstFinger = null; } if (moveDrawingIndex == -1 && resizeDrawingIndex == -1 && System.currentTimeMillis() - touchStartTime < 400 && Math.abs(event.getX() - moveDrawingStartX) + Math.abs(event.getY() - moveDrawingStartY) < 8) { if (resizeDrawingCorner != null && selectedDrawing != null) { if (resizeDrawingCorner == "tl" && selectedDrawing instanceof TextDrawing) { //promptForText((TextDrawing)selectedDrawing); } else if (resizeDrawingCorner == "tr") { //maybeRemoveDrawing(selectedDrawing); } } else { //promptForText((int) event.getX(), (int) event.getY()); } } moveDrawingIndex = -1; Log.d(TAG, "Stop dragging overlay"); // TODO: add to undo stack return true; } else if (firstFinger != null && secondFinger != null && action == MotionEvent.ACTION_MOVE) { MotionEvent.PointerCoords coords1 = new MotionEvent.PointerCoords(); event.getPointerCoords(0, coords1); Log.d(TAG, "coords1: " + coords1.x + " " + coords1.y); MotionEvent.PointerCoords coords2 = new MotionEvent.PointerCoords(); event.getPointerCoords(1, coords2); Log.d(TAG, "coords2: " + coords2.x + " " + coords2.y); float xDist = firstFinger.x - secondFinger.x, yDist = firstFinger.y - secondFinger.y; float origAngle = (float) Math.atan2(yDist, xDist); if (origAngle < 0) origAngle += Math.PI * 2; float lastDistance = (float) Math.sqrt(xDist * xDist + yDist * yDist); xDist = coords2.x - coords1.x; yDist = coords2.y - coords1.y; float newDistance = (float) Math.sqrt(xDist * xDist + yDist * yDist); float newAngle = (float) Math.atan2(yDist, xDist); if (newAngle < 0) newAngle += Math.PI * 2; if (newAngle - origAngle > Math.PI / 2) { origAngle += Math.PI; } else if (origAngle - newAngle > Math.PI / 2) { newAngle += Math.PI; } firstFinger.set(coords1.x, coords1.y); secondFinger = new PointF(coords2.x, coords2.y); if (selectedDrawing != null) { selectedDrawing.resizeBy(newDistance / lastDistance); selectedDrawing.rotateBy(newAngle - origAngle); invalidate(); } } else if (moveDrawingIndex >= 0 && moveDrawingIndex < overlays.size() && action == MotionEvent.ACTION_MOVE) { float x = event.getX(); float y = event.getY(); overlays.get(moveDrawingIndex).moveBy((int) ((x - moveDrawingStartX) * getDrawingDensity()), (int) ((y - moveDrawingStartY) * getDrawingDensity())); // TODO: only invalidate relevant Rect invalidate(); moveDrawingStartX = x; moveDrawingStartY = y; return true; } else if (resizeDrawingIndex >= 0 && resizeDrawingIndex < overlays.size() && action == MotionEvent.ACTION_MOVE) { float x = event.getX(); float y = event.getY(); overlays.get(resizeDrawingIndex).resizeCorner(resizeDrawingCorner, (int) (x - moveDrawingStartX), (int) (y - moveDrawingStartY)); // TODO: only invalidate relevant Rect invalidate(); moveDrawingStartX = x; moveDrawingStartY = y; return true; } return false; } if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) { int j = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) ? event.getActionIndex() : 0; mTmpSpot.update(event.getX(j), event.getY(j), event.getSize(j), event.getPressure(j) + event.getSize(j), time, getToolTypeCompat(event, j)); mStrokes[event.getPointerId(j)].add(mTmpSpot); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) { mStrokes[event.getPointerId(j)].finish(time); } } else if (action == MotionEvent.ACTION_MOVE) { if (dbgX >= 0) { dbgRect.set(dbgX - 1, dbgY - 1, dbgX + 1, dbgY + 1); } for (int i = 0; i < N; i++) { for (int j = 0; j < P; j++) { mTmpSpot.update(event.getHistoricalX(j, i), event.getHistoricalY(j, i), event.getHistoricalSize(j, i), event.getHistoricalPressure(j, i) + event.getHistoricalSize(j, i), event.getHistoricalEventTime(i), getToolTypeCompat(event, j)); if ((mDebugFlags & FLAG_DEBUG_STROKES) != 0) { if (dbgX >= 0) { //mTiledCanvas.drawLine(dbgX, dbgY, mTmpSpot.x, mTmpSpot.y, mDebugPaints[3]); } dbgX = mTmpSpot.x; dbgY = mTmpSpot.y; dbgRect.union(dbgX - 1, dbgY - 1, dbgX + 1, dbgY + 1); } mStrokes[event.getPointerId(j)].add(mTmpSpot); } } for (int j = 0; j < P; j++) { mTmpSpot.update(event.getX(j), event.getY(j), event.getSize(j), event.getPressure(j) + event.getSize(j), time, getToolTypeCompat(event, j)); if ((mDebugFlags & FLAG_DEBUG_STROKES) != 0) { if (dbgX >= 0) { //mTiledCanvas.drawLine(dbgX, dbgY, mTmpSpot.x, mTmpSpot.y, mDebugPaints[3]); } dbgX = mTmpSpot.x; dbgY = mTmpSpot.y; dbgRect.union(dbgX - 1, dbgY - 1, dbgX + 1, dbgY + 1); } mStrokes[event.getPointerId(j)].add(mTmpSpot); } if ((mDebugFlags & FLAG_DEBUG_STROKES) != 0) { Rect dirty = new Rect(); dbgRect.roundOut(dirty); invalidate(dirty); } } if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { for (int j = 0; j < P; j++) { mStrokes[event.getPointerId(j)].finish(time); } dbgX = dbgY = -1; } return true; }