private void DrawScale(Canvas canvas) { canvas.Save(SaveFlags.Matrix); // On canvas, North is 0 degrees, East is 90 degrees, South is 180 etc. // We start the scale somewhere South-West so we need to first rotate the canvas. canvas.Rotate(mScaleRotation, 0.5f, 0.5f); int totalTicks = mDivisions * mSubdivisions + 1; for (int i = 0; i < totalTicks; i++) { float y1 = mScaleRect.Top; float y2 = y1 + 0.015f; // height of division float y3 = y1 + 0.045f; // height of subdivision float value = GetValueForTick(i); Paint paint = GetRangePaint(value); float mod = value % mDivisionValue; if ((Math.Abs(mod - 0) < 0.001) || (Math.Abs(mod - mDivisionValue) < 0.001)) { // Draw a division tick canvas.DrawLine(0.5f, y1, 0.5f, y3, paint); // Draw the text 0.15 away from the division tick DrawTextOnCanvasWithMagnifier(canvas, ValueString(value), 0.5f, y3 + 0.045f, paint); } else { // Draw a subdivision tick canvas.DrawLine(0.5f, y1, 0.5f, y2, paint); } canvas.Rotate(mSubdivisionAngle, 0.5f, 0.5f); } canvas.Restore(); }
private void ComputeCurrentValue() { if (!(Math.Abs(mCurrentValue - mTargetValue) > 0.01f)) { return; } if (-1 != mNeedleLastMoved) { float time = (JavaSystem.CurrentTimeMillis() - mNeedleLastMoved) / 1000.0f; float direction = Math.Signum(mNeedleVelocity); if (Math.Abs(mNeedleVelocity) < 90.0f) { mNeedleAcceleration = 5.0f * (mTargetValue - mCurrentValue); } else { mNeedleAcceleration = 0.0f; } mNeedleAcceleration = 5.0f * (mTargetValue - mCurrentValue); mCurrentValue += mNeedleVelocity * time; mNeedleVelocity += mNeedleAcceleration * time; if ((mTargetValue - mCurrentValue) * direction < 0.01f * direction) { mCurrentValue = mTargetValue; mNeedleVelocity = 0.0f; mNeedleAcceleration = 0.0f; mNeedleLastMoved = -1L; } else { mNeedleLastMoved = JavaSystem.CurrentTimeMillis(); } Invalidate(); } else { mNeedleLastMoved = JavaSystem.CurrentTimeMillis(); ComputeCurrentValue(); } }
public override bool OnTouchEvent(MotionEvent ev) { if (mIsVerbose) { Log.Verbose(TAG, "onTouchEvent: " + ((int)ev.Action & MotionEventCompat.ActionMask)); } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.Obtain(); } mVelocityTracker.AddMovement(ev); var action = ev.Action; switch ((int)action & MotionEventCompat.ActionMask) { case (int)MotionEventActions.Down: // If being flinged and user touches, stop the fling. isFinished // will be false if being flinged. if (!mScroller.IsFinished) { mScroller.AbortAnimation(); } // Remember where the motion event started mDownMotionX = ev.GetX(); mDownMotionY = ev.GetY(); mDownScrollX = ScrollX; mActivePointerId = MotionEventCompat.GetPointerId(ev, 0); break; case (int)MotionEventActions.Move: if (mIsVerbose) { Log.Verbose(TAG, "mTouchState=" + mTouchState); } if (mTouchState == TOUCH_STATE_SCROLLING) { // Scroll to follow the motion event int pointerIndex = MotionEventCompat.FindPointerIndex(ev, mActivePointerId); float x = MotionEventCompat.GetX(ev, pointerIndex); View lastChild = GetChildAt(ChildCount - 1); int maxScrollX = lastChild.Right - Width; ScrollTo(Math.Max(0, Math.Min(maxScrollX, (int)(mDownScrollX + mDownMotionX - x ))), 0); if (mOnScrollListener != null) { mOnScrollListener.OnScroll(GetCurrentScreenFraction()); } } else if (mTouchState == TOUCH_STATE_REST) { if (mLocked) { // we're locked on the current screen, don't allow moving break; } /* * Locally do absolute value. mLastMotionX is set to the y value * of the down event. */ int pointerIndex = MotionEventCompat.FindPointerIndex(ev, mActivePointerId); float x = MotionEventCompat.GetX(ev, pointerIndex); float y = MotionEventCompat.GetY(ev, pointerIndex); int xDiff = (int)Math.Abs(x - mDownMotionX); int yDiff = (int)Math.Abs(y - mDownMotionY); bool xPaged = xDiff > mPagingTouchSlop; bool xMoved = xDiff > mTouchSlop; bool yMoved = yDiff > mTouchSlop; if (xMoved || yMoved) { if (xPaged) { // Scroll if the user moved far enough along the X axis mTouchState = TOUCH_STATE_SCROLLING; } // Either way, cancel any pending longpress if (mAllowLongPress) { mAllowLongPress = false; // Try canceling the long press. It could also have been scheduled // by a distant descendant, so use the mAllowLongPress flag to block // everything View currentScreen = GetScreenAt(mCurrentScreen); if (currentScreen != null) { currentScreen.CancelLongPress(); } } } } break; case (int)MotionEventActions.Up: if (mTouchState == TOUCH_STATE_SCROLLING) { int activePointerId = mActivePointerId; int pointerIndex = MotionEventCompat.FindPointerIndex(ev, activePointerId); float x = MotionEventCompat.GetX(ev, pointerIndex); VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.ComputeCurrentVelocity(1000, mMaximumVelocity); //TODO(minsdk8): int velocityX = (int) MotionEventUtils.getXVelocity(velocityTracker, activePointerId); int velocityX = (int)velocityTracker.XVelocity; bool isFling = Math.Abs(mDownMotionX - x) > MIN_LENGTH_FOR_FLING; float scrolledPos = GetCurrentScreenFraction(); int whichScreen = Math.Round(scrolledPos); if (isFling && mIsVerbose) { Log.Verbose(TAG, "isFling, whichScreen=" + whichScreen + " scrolledPos=" + scrolledPos + " mCurrentScreen=" + mCurrentScreen + " velocityX=" + velocityX); } if (isFling && velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { // Fling hard enough to move left // Don't fling across more than one screen at a time. int bound = scrolledPos <= whichScreen ? mCurrentScreen - 1 : mCurrentScreen; SnapToScreen(Math.Min(whichScreen, bound)); } else if (isFling && velocityX < -SNAP_VELOCITY && mCurrentScreen < ChildCount - 1) { // Fling hard enough to move right // Don't fling across more than one screen at a time. int bound = scrolledPos >= whichScreen ? mCurrentScreen + 1 : mCurrentScreen; SnapToScreen(Math.Max(whichScreen, bound)); } else { SnapToDestination(); } } else { PerformClick(); } mTouchState = TOUCH_STATE_REST; mActivePointerId = INVALID_POINTER; // Can't do this -> // Intentially fall through to cancel mTouchState = TOUCH_STATE_REST; mActivePointerId = INVALID_POINTER; if (mVelocityTracker != null) { mVelocityTracker.Recycle(); mVelocityTracker = null; } break; case (int)MotionEventActions.Cancel: mTouchState = TOUCH_STATE_REST; mActivePointerId = INVALID_POINTER; if (mVelocityTracker != null) { mVelocityTracker.Recycle(); mVelocityTracker = null; } break; case (int)MotionEventCompat.ActionPointerUp: OnSecondaryPointerUp(ev); break; } return(true); }
public bool OnTouch(View view, MotionEvent motionEvent) { if (view != LastTouchedView) { Count = 0; LastTouchedView = view; } if (motionEvent.Action == MotionEventActions.Up) { Count = 0; return(true); } if (Count < 2) { if (Count == 0) { HasCloned = false; FirstX = motionEvent.GetX(); FirstY = motionEvent.GetY(); } Count++; return(true); } float dX = Math.Abs(motionEvent.GetX() - FirstX); float dY = Math.Abs(motionEvent.GetY() - FirstY); if (LastTouchedView.Parent is RecyclerView && (dX > dY) || LastTouchedView.Parent is LinearLayout && dY > dX) { return(false); } if (view is RecyclerBlockView recyclerBlockView) { if (!HasCloned) { // OnTouchListener is set in DragAction.OnDrop, and OnDragListener doesn't need to be set on the BlockView, as it's set in the ctor of ContainerBlockView ! LastClonedRbv = recyclerBlockView.Clone(); HasCloned = true; } view = LastClonedRbv; } SaveViewPosition(view); ClipData clipData = new ClipData("dragged", new[] { ClipDescription.MimetypeTextPlain }, new ClipData.Item("dragged")); if (view.StartDragAndDrop(clipData, new View.DragShadowBuilder(LastTouchedView), view, 0)) { view.Visibility = ViewStates.Invisible; } else { if (LastTouchedView is RecyclerBlockView blockView) { blockView.RemoveCloneInstance(); } } return(true); }