public override void ComputeScroll() { if (!_dragHelper.ContinueSettling(true)) { return; } if (!_canSlide) { _dragHelper.Abort(); return; } ViewCompat.PostInvalidateOnAnimation(this); }
private void IncrementSnapback() { if (scroller.IsFinished) { return; } var more = scroller.ComputeScrollOffset(); Header.OffsetTopAndBottom(current_scroll_y - scroller.CurrY); ((View)ContentView).OffsetTopAndBottom(current_scroll_y - scroller.CurrY); current_scroll_y = scroller.CurrY; if (more) { ViewCompat.PostInvalidateOnAnimation(this); } }
private bool SmoothSlideTo(float slideOffset) { if (!_canSlide) { return(false); } var y = _isSlidingUp ? (int)(SlidingTop + slideOffset * _slideRange) : (int)(SlidingTop - slideOffset * _slideRange); if (!_dragHelper.SmoothSlideViewTo(_slideableView, _slideableView.Left, y)) { return(false); } SetAllChildrenVisible(); ViewCompat.PostInvalidateOnAnimation(this); return(true); }
/** * Close the panel to hide the secondary view * @param animation true to animate the close motion. {@link SwipeListener} won't be * called if is animation is false. */ public void close(bool animation) { CoreUtility.ExecuteMethod("close", delegate() { mIsOpenBeforeInit = false; mAborted = false; if (animation) { mState = STATE_CLOSING; mDragHelper.SmoothSlideViewTo(mMainView, mRectMainClose.Left, mRectMainClose.Top); if (mDragStateChangeListener != null) { mDragStateChangeListener.onDragStateChanged(mState); } } else { mState = STATE_CLOSE; mDragHelper.Abort(); mMainView.Layout( mRectMainClose.Left, mRectMainClose.Top, mRectMainClose.Right, mRectMainClose.Bottom ); mSecondaryView.Layout( mRectSecClose.Left, mRectSecClose.Top, mRectSecClose.Right, mRectSecClose.Bottom ); } ViewCompat.PostInvalidateOnAnimation(this); }); }
public override void OnViewPositionChanged(View changedView, int left, int top, int dx, int dy) { base.OnViewPositionChanged(changedView, left, top, dx, dy); if (_layout.mMode == MODE_SAME_LEVEL) { if (_layout.mDragEdge == DRAG_EDGE_LEFT || _layout.mDragEdge == DRAG_EDGE_RIGHT) { _layout.mSecondaryView.OffsetLeftAndRight(dx); } else { _layout.mSecondaryView.OffsetTopAndBottom(dy); } } bool isMoved = (_layout.mMainView.Left != _layout.mLastMainLeft) || (_layout.mMainView.Top != _layout.mLastMainTop); if (_layout.mSwipeListener != null && isMoved) { if (_layout.mMainView.Left == _layout.mRectMainClose.Left && _layout.mMainView.Top == _layout.mRectMainClose.Top) { _layout.mSwipeListener.onClosed(_layout); } else if (_layout.mMainView.Left == _layout.mRectMainOpen.Left && _layout.mMainView.Top == _layout.mRectMainOpen.Top) { _layout.mSwipeListener.onOpened(_layout); } else { _layout.mSwipeListener.onSlide(_layout, getSlideOffset()); } } _layout.mLastMainLeft = _layout.mMainView.Left; _layout.mLastMainTop = _layout.mMainView.Top; ViewCompat.PostInvalidateOnAnimation(_layout); }
public override bool OnTouchEvent(MotionEvent e) { if (!IsPullEnabled) { return(base.OnTouchEvent(e)); } if (null == ContentView) { return(base.OnTouchEvent(e)); } if (ContentView is AbsListView && ((AbsListView)ContentView).FastScrollEnabled) { // An adimittedly crude way to determine if touch is in fast scroll, but // should accomplish the goal of not displaying ptr header. // This is crude because there is not a definitive way to determine // a) if the fast scroller is visible or // b) the width of the scroller if (Resources.DisplayMetrics.WidthPixels - e.RawX < fastscroll_thumb_width) { return(false); // let the list view handle this } } switch (e.ActionMasked) { case MotionEventActions.Down: last_touch_y = ContentView.IsAtTop ? (int)e.RawY : -1; if (!ContentView.IsAtTop) { send_down_event = false; // because this event will reach the ContentView } else { should_send_down_before_up = true; } return(ContentView.IsAtTop); case MotionEventActions.Move: if (did_steal_event_stream && current_scroll_y >= 0) { if (send_down_event) { did_steal_event_stream = false; send_down_event = false; ContentView.IgnoreTouchEvents = false; SendFakeEvent(e, MotionEventActions.Down); } return(true); } if (last_touch_y == -1) { last_touch_y = (int)e.RawY; return(true); } var y_delta = last_touch_y - (int)e.RawY; last_touch_y = (int)e.RawY; bool isMovingUp = y_delta > 0; if (isMovingUp && current_scroll_y >= 0 || !ContentView.IsAtTop) { should_send_down_before_up = false; ContentView.ForceHandleTouchEvent(e); return(true); } if (ContentView.IsAtTop) { var new_scroll_to = isMovingUp ? (int)y_delta : (int)(y_delta * PullDownTensionFactor); // see if this will fully hide the header if (current_scroll_y < 0 && current_scroll_y + new_scroll_to > 0) { // only scroll enough to hide the header new_scroll_to = -current_scroll_y; } current_scroll_y += new_scroll_to; Header.OffsetTopAndBottom(-new_scroll_to); ((View)ContentView).OffsetTopAndBottom(-new_scroll_to); ViewCompat.PostInvalidateOnAnimation(this); if (current_scroll_y == 0) { ContentView.IgnoreTouchEvents = false; return(true); } else { should_cancel_before_up = true; should_send_down_before_up = false; } if (Math.Abs(current_scroll_y) >= header_measured_height) { if (refresh_state != PullToRefresharpRefreshState.Refreshing) { SetPullDownIconProgress(1); UpdateRefreshState(PullToRefresharpRefreshState.ReleaseToRefresh); } } else { // Don't update anything if we are refreshing. if (refresh_state != PullToRefresharpRefreshState.Refreshing) { SetPullDownIconProgress((float)Math.Abs(current_scroll_y) / (float)header_measured_height); UpdateRefreshState(PullToRefresharpRefreshState.PullToRefresh); } } return(true); } return(false); case MotionEventActions.Up: return(HandleUpEvent(e)); } return(base.OnTouchEvent(e)); }
public void Draw(Canvas canvas) { var clipPath = new Path(); clipPath.AddRoundRect(_bounds, _cornerRadius, _cornerRadius, Path.Direction.Cw); int width = (int)_bounds.Width(); int height = (int)_bounds.Height(); int cx = width / 2; int cy = height / 2; bool drawTriggerWhileFinishing = false; int restoreCount = canvas.Save(); canvas.ClipPath(clipPath); if (_running || _finishTime > 0) { long now = AnimationUtils.CurrentAnimationTimeMillis(); long elapsed = (now - _startTime) % ANIMATION_DURATION_MS; long iterations = (now - _startTime) / ANIMATION_DURATION_MS; float rawProgress = (elapsed / (ANIMATION_DURATION_MS / 100f)); if (!_running) { if ((now - _finishTime) >= FINISH_ANIMATION_DURATION_MS) { _finishTime = 0; return; } // Otherwise, use a 0 opacity alpha layer to clear the animation // from the inside out. This layer will prevent the circles from // drawing within its bounds. long finishEplapsed = (now - _finishTime) % FINISH_ANIMATION_DURATION_MS; float finishProgress = (finishEplapsed / (FINISH_ANIMATION_DURATION_MS / 100f)); float pct = finishProgress / 100f; float clearRadius = width / 2 * _interpolator.GetInterpolation(pct); _rectF.Set(cx - clearRadius, 0, cx + clearRadius, height); canvas.SaveLayerAlpha(_rectF, 0, 0); // Only draw the trigger if there is a space in the center of // this refreshing view that needs to be filled in by the // trigger. If the progress view is just still animating, let it // continue animating. drawTriggerWhileFinishing = true; } // First fill in with the last color that would have finished drawing. if (iterations == 0) { canvas.DrawColor(ColorUtils.FromUint(_color1)); } else { if (rawProgress >= 0 && rawProgress < 25) { canvas.DrawColor(ColorUtils.FromUint(_color4)); } else if (rawProgress >= 25 && rawProgress < 50) { canvas.DrawColor(ColorUtils.FromUint(_color1)); } else if (rawProgress >= 50 && rawProgress < 75) { canvas.DrawColor(ColorUtils.FromUint(_color2)); } else { canvas.DrawColor(ColorUtils.FromUint(_color3)); } } // Then draw up to 4 overlapping concentric circles of varying radii, based on how far // along we are in the cycle. // progress 0-50 draw mColor2 // progress 25-75 draw mColor3 // progress 50-100 draw mColor4 // progress 75 (wrap to 25) draw mColor1 if (rawProgress >= 0 && rawProgress <= 25) { float pct = (rawProgress + 25) * 2 / 100f; DrawCircle(canvas, cx, cy, _color1, pct); } if (rawProgress >= 0 && rawProgress <= 50) { float pct = ((rawProgress * 2) / 100f); DrawCircle(canvas, cx, cy, _color2, pct); } if (rawProgress >= 25 && rawProgress <= 75) { float pct = (((rawProgress - 25) * 2) / 100f); DrawCircle(canvas, cx, cy, _color3, pct); } if (rawProgress >= 50 && rawProgress <= 100) { float pct = (((rawProgress - 50) * 2) / 100f); DrawCircle(canvas, cx, cy, _color4, pct); } if ((rawProgress >= 75 && rawProgress <= 100)) { float pct = (((rawProgress - 75) * 2) / 100f); DrawCircle(canvas, cx, cy, _color1, pct); } if (_triggerPercentage > 0 && drawTriggerWhileFinishing) { canvas.RestoreToCount(restoreCount); restoreCount = canvas.Save(); canvas.ClipPath(clipPath); DrawTrigger(canvas, cx, cy); } ViewCompat.PostInvalidateOnAnimation(_parent); } else if (_triggerPercentage > 0 && _triggerPercentage < 1.0) { DrawTrigger(canvas, cx, cy); } canvas.RestoreToCount(restoreCount); }
public void draw(Canvas canvas) { int width = mBounds.Width(); int height = mBounds.Height(); int cx = width / 2; int cy = height / 2; Boolean drawTriggerWhileFinishing = false; int restoreCount = canvas.Save(); canvas.ClipRect(mBounds); if (mRunning || (mFinishTime > 0)) { long now = AnimationUtils.CurrentAnimationTimeMillis(); long elapsed = (now - mStartTime) % ANIMATION_DURATION_MS; long iterations = (now - mStartTime) / ANIMATION_DURATION_MS; float rawProgress = (elapsed / (ANIMATION_DURATION_MS / 100f)); // If we're not running anymore, that means we're running through // the finish animation. if (!mRunning) { // If the finish animation is done, don't draw anything, and // don't repost. if ((now - mFinishTime) >= FINISH_ANIMATION_DURATION_MS) { mFinishTime = 0; return; } // Otherwise, use a 0 opacity alpha layer to clear the animation // from the inside out. This layer will prevent the circles from // drawing within its bounds. long finishElapsed = (now - mFinishTime) % FINISH_ANIMATION_DURATION_MS; float finishProgress = (finishElapsed / (FINISH_ANIMATION_DURATION_MS / 100f)); float pct = (finishProgress / 100f); // Radius of the circle is half of the screen. float clearRadius = width / 2; //* INTERPOLATOR.getInterpolation(pct); mClipRect.Set(cx - clearRadius, 0, cx + clearRadius, height); canvas.SaveLayerAlpha(mClipRect, 0, 0); // Only draw the trigger if there is a space in the center of // this refreshing view that needs to be filled in by the // trigger. If the progress view is just still animating, let it // continue animating. drawTriggerWhileFinishing = true; } // First fill in with the last color that would have finished drawing. if (iterations == 0) { canvas.DrawColor(Android.Graphics.Color.Blue); } else { if (rawProgress >= 0 && rawProgress < 25) { canvas.DrawColor(Android.Graphics.Color.AliceBlue); } else if (rawProgress >= 25 && rawProgress < 50) { canvas.DrawColor(Android.Graphics.Color.Blue); } else if (rawProgress >= 50 && rawProgress < 75) { canvas.DrawColor(Android.Graphics.Color.BlueViolet); } else { canvas.DrawColor(Android.Graphics.Color.CadetBlue); } } // Then draw up to 4 overlapping concentric circles of varying radii, based on how far // along we are in the cycle. // progress 0-50 draw mColor2 // progress 25-75 draw mColor3 // progress 50-100 draw mColor4 // progress 75 (wrap to 25) draw mColor1 if ((rawProgress >= 0 && rawProgress <= 25)) { float pct = (((rawProgress + 25) * 2) / 100f); drawCircle(canvas, cx, cy, mColor1, pct); } if (rawProgress >= 0 && rawProgress <= 50) { float pct = ((rawProgress * 2) / 100f); drawCircle(canvas, cx, cy, mColor2, pct); } if (rawProgress >= 25 && rawProgress <= 75) { float pct = (((rawProgress - 25) * 2) / 100f); drawCircle(canvas, cx, cy, mColor3, pct); } if (rawProgress >= 50 && rawProgress <= 100) { float pct = (((rawProgress - 50) * 2) / 100f); drawCircle(canvas, cx, cy, mColor4, pct); } if ((rawProgress >= 75 && rawProgress <= 100)) { float pct = (((rawProgress - 75) * 2) / 100f); drawCircle(canvas, cx, cy, mColor1, pct); } if (mTriggerPercentage > 0 && drawTriggerWhileFinishing) { // There is some portion of trigger to draw. Restore the canvas, // then draw the trigger. Otherwise, the trigger does not appear // until after the bar has finished animating and appears to // just jump in at a larger width than expected. canvas.RestoreToCount(restoreCount); restoreCount = canvas.Save(); canvas.ClipRect(mBounds); drawTrigger(canvas, cx, cy); } // Keep running until we finish out the last cycle. ViewCompat.PostInvalidateOnAnimation(mParent); } else { // Otherwise if we're in the middle of a trigger, draw that. if (mTriggerPercentage > 0 && mTriggerPercentage <= 1.0) { drawTrigger(canvas, cx, cy); } } canvas.RestoreToCount(restoreCount); }