Пример #1
0
 /// <summary>To be called when the critical span is complete (i.e.</summary>
 /// <remarks>
 /// To be called when the critical span is complete (i.e. the
 /// animation is done animating).  This can be called on any
 /// thread (even a different one from where the animation was
 /// taking place), but that's only a defensive implementation
 /// measure.  It really makes no sense for you to call this on
 /// thread other than that where you created it.
 /// </remarks>
 /// <hide></hide>
 public virtual void finish()
 {
     android.os.StrictMode.ThreadSpanState state = mContainerState;
     lock (state)
     {
         if (mName == null)
         {
             return;
         }
         if (mPrev != null)
         {
             mPrev.mNext = mNext;
         }
         if (mNext != null)
         {
             mNext.mPrev = mPrev;
         }
         if (state.mActiveHead == this)
         {
             state.mActiveHead = mNext;
         }
         state.mActiveSize--;
         if (LOG_V)
         {
             android.util.Log.d(TAG, "Span finished=" + mName + "; size=" + state.mActiveSize);
         }
         this.mCreateMillis = -1;
         this.mName         = null;
         this.mPrev         = null;
         this.mNext         = null;
         if (state.mFreeListSize < 5)
         {
             this.mNext          = state.mFreeListHead;
             state.mFreeListHead = this;
             state.mFreeListSize++;
         }
     }
 }
Пример #2
0
		public override bool onInterceptTouchEvent(android.view.MotionEvent ev)
		{
			int action = ev.getAction();
			if ((action == android.view.MotionEvent.ACTION_MOVE) && (mIsBeingDragged))
			{
				return true;
			}
			switch (action & android.view.MotionEvent.ACTION_MASK)
			{
				case android.view.MotionEvent.ACTION_MOVE:
				{
					int activePointerId = mActivePointerId;
					if (activePointerId == INVALID_POINTER)
					{
						// If we don't have a valid id, the touch down wasn't on content.
						break;
					}
					int pointerIndex = ev.findPointerIndex(activePointerId);
					float y = ev.getY(pointerIndex);
					int yDiff = (int)System.Math.Abs(y - mLastMotionY);
					if (yDiff > mTouchSlop)
					{
						mIsBeingDragged = true;
						mLastMotionY = y;
						initVelocityTrackerIfNotExists();
						mVelocityTracker.addMovement(ev);
						if (mScrollStrictSpan == null)
						{
							mScrollStrictSpan = android.os.StrictMode.enterCriticalSpan("ScrollView-scroll");
						}
					}
					break;
				}

				case android.view.MotionEvent.ACTION_DOWN:
				{
					float y = ev.getY();
					if (!inChild((int)ev.getX(), (int)y))
					{
						mIsBeingDragged = false;
						recycleVelocityTracker();
						break;
					}
					mLastMotionY = y;
					mActivePointerId = ev.getPointerId(0);
					initOrResetVelocityTracker();
					mVelocityTracker.addMovement(ev);
					mIsBeingDragged = !mScroller.isFinished();
					if (mIsBeingDragged && mScrollStrictSpan == null)
					{
						mScrollStrictSpan = android.os.StrictMode.enterCriticalSpan("ScrollView-scroll");
					}
					break;
				}

				case android.view.MotionEvent.ACTION_CANCEL:
				case android.view.MotionEvent.ACTION_UP:
				{
					mIsBeingDragged = false;
					mActivePointerId = INVALID_POINTER;
					recycleVelocityTracker();
					if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange()))
					{
						invalidate();
					}
					break;
				}

				case android.view.MotionEvent.ACTION_POINTER_UP:
				{
					onSecondaryPointerUp(ev);
					break;
				}
			}
			return mIsBeingDragged;
		}
Пример #3
0
		public override bool onTouchEvent(android.view.MotionEvent ev)
		{
			initVelocityTrackerIfNotExists();
			mVelocityTracker.addMovement(ev);
			int action = ev.getAction();
			switch (action & android.view.MotionEvent.ACTION_MASK)
			{
				case android.view.MotionEvent.ACTION_DOWN:
				{
					mIsBeingDragged = getChildCount() != 0;
					if (!mIsBeingDragged)
					{
						return false;
					}
					if (!mScroller.isFinished())
					{
						mScroller.abortAnimation();
						if (mFlingStrictSpan != null)
						{
							mFlingStrictSpan.finish();
							mFlingStrictSpan = null;
						}
					}
					// Remember where the motion event started
					mLastMotionY = ev.getY();
					mActivePointerId = ev.getPointerId(0);
					break;
				}

				case android.view.MotionEvent.ACTION_MOVE:
				{
					if (mIsBeingDragged)
					{
						// Scroll to follow the motion event
						int activePointerIndex = ev.findPointerIndex(mActivePointerId);
						float y = ev.getY(activePointerIndex);
						int deltaY = (int)(mLastMotionY - y);
						mLastMotionY = y;
						int oldX = mScrollX;
						int oldY = mScrollY;
						int range = getScrollRange();
						int overscrollMode = getOverScrollMode();
						bool canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS
							 && range > 0);
						if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true))
						{
							// Break our velocity if we hit a scroll barrier.
							mVelocityTracker.clear();
						}
						onScrollChanged(mScrollX, mScrollY, oldX, oldY);
						if (canOverscroll)
						{
							int pulledToY = oldY + deltaY;
							if (pulledToY < 0)
							{
								mEdgeGlowTop.onPull((float)deltaY / getHeight());
								if (!mEdgeGlowBottom.isFinished())
								{
									mEdgeGlowBottom.onRelease();
								}
							}
							else
							{
								if (pulledToY > range)
								{
									mEdgeGlowBottom.onPull((float)deltaY / getHeight());
									if (!mEdgeGlowTop.isFinished())
									{
										mEdgeGlowTop.onRelease();
									}
								}
							}
							if (mEdgeGlowTop != null && (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished
								()))
							{
								invalidate();
							}
						}
					}
					break;
				}

				case android.view.MotionEvent.ACTION_UP:
				{
					if (mIsBeingDragged)
					{
						android.view.VelocityTracker velocityTracker = mVelocityTracker;
						velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
						int initialVelocity = (int)velocityTracker.getYVelocity(mActivePointerId);
						if (getChildCount() > 0)
						{
							if ((System.Math.Abs(initialVelocity) > mMinimumVelocity))
							{
								fling(-initialVelocity);
							}
							else
							{
								if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange()))
								{
									invalidate();
								}
							}
						}
						mActivePointerId = INVALID_POINTER;
						endDrag();
					}
					break;
				}

				case android.view.MotionEvent.ACTION_CANCEL:
				{
					if (mIsBeingDragged && getChildCount() > 0)
					{
						if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange()))
						{
							invalidate();
						}
						mActivePointerId = INVALID_POINTER;
						endDrag();
					}
					break;
				}

				case android.view.MotionEvent.ACTION_POINTER_DOWN:
				{
					int index = ev.getActionIndex();
					float y = ev.getY(index);
					mLastMotionY = y;
					mActivePointerId = ev.getPointerId(index);
					break;
				}

				case android.view.MotionEvent.ACTION_POINTER_UP:
				{
					onSecondaryPointerUp(ev);
					mLastMotionY = ev.getY(ev.findPointerIndex(mActivePointerId));
					break;
				}
			}
			return true;
		}
Пример #4
0
		private void endDrag()
		{
			mIsBeingDragged = false;
			recycleVelocityTracker();
			if (mEdgeGlowTop != null)
			{
				mEdgeGlowTop.onRelease();
				mEdgeGlowBottom.onRelease();
			}
			if (mScrollStrictSpan != null)
			{
				mScrollStrictSpan.finish();
				mScrollStrictSpan = null;
			}
		}
Пример #5
0
		/// <summary>Fling the scroll view</summary>
		/// <param name="velocityY">
		/// The initial velocity in the Y direction. Positive
		/// numbers mean that the finger/cursor is moving down the screen,
		/// which means we want to scroll towards the top.
		/// </param>
		public virtual void fling(int velocityY)
		{
			if (getChildCount() > 0)
			{
				int height = getHeight() - mPaddingBottom - mPaddingTop;
				int bottom = getChildAt(0).getHeight();
				mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, System.Math.Max(0, bottom
					 - height), 0, height / 2);
				bool movingDown = velocityY > 0;
				if (mFlingStrictSpan == null)
				{
					mFlingStrictSpan = android.os.StrictMode.enterCriticalSpan("ScrollView-fling");
				}
				invalidate();
			}
		}
Пример #6
0
		protected internal override void onDetachedFromWindow()
		{
			base.onDetachedFromWindow();
			if (mScrollStrictSpan != null)
			{
				mScrollStrictSpan.finish();
				mScrollStrictSpan = null;
			}
			if (mFlingStrictSpan != null)
			{
				mFlingStrictSpan.finish();
				mFlingStrictSpan = null;
			}
		}
Пример #7
0
		public override void computeScroll()
		{
			if (mScroller.computeScrollOffset())
			{
				// This is called at drawing time by ViewGroup.  We don't want to
				// re-show the scrollbars at this point, which scrollTo will do,
				// so we replicate most of scrollTo here.
				//
				//         It's a little odd to call onScrollChanged from inside the drawing.
				//
				//         It is, except when you remember that computeScroll() is used to
				//         animate scrolling. So unless we want to defer the onScrollChanged()
				//         until the end of the animated scrolling, we don't really have a
				//         choice here.
				//
				//         I agree.  The alternative, which I think would be worse, is to post
				//         something and tell the subclasses later.  This is bad because there
				//         will be a window where mScrollX/Y is different from what the app
				//         thinks it is.
				//
				int oldX = mScrollX;
				int oldY = mScrollY;
				int x = mScroller.getCurrX();
				int y = mScroller.getCurrY();
				if (oldX != x || oldY != y)
				{
					int range = getScrollRange();
					int overscrollMode = getOverScrollMode();
					bool canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS
						 && range > 0);
					overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range, 0, mOverflingDistance, false
						);
					onScrollChanged(mScrollX, mScrollY, oldX, oldY);
					if (canOverscroll)
					{
						if (y < 0 && oldY >= 0)
						{
							mEdgeGlowTop.onAbsorb((int)mScroller.getCurrVelocity());
						}
						else
						{
							if (y > range && oldY <= range)
							{
								mEdgeGlowBottom.onAbsorb((int)mScroller.getCurrVelocity());
							}
						}
					}
				}
				awakenScrollBars();
				// Keep on drawing until the animation has finished.
				postInvalidate();
			}
			else
			{
				if (mFlingStrictSpan != null)
				{
					mFlingStrictSpan.finish();
					mFlingStrictSpan = null;
				}
			}
		}
Пример #8
0
		/// <summary>
		/// Like
		/// <see cref="android.view.View.scrollBy(int, int)">android.view.View.scrollBy(int, int)
		/// 	</see>
		/// , but scroll smoothly instead of immediately.
		/// </summary>
		/// <param name="dx">the number of pixels to scroll by on the X axis</param>
		/// <param name="dy">the number of pixels to scroll by on the Y axis</param>
		public void smoothScrollBy(int dx, int dy)
		{
			if (getChildCount() == 0)
			{
				// Nothing to do.
				return;
			}
			long duration = android.view.animation.AnimationUtils.currentAnimationTimeMillis(
				) - mLastScroll;
			if (duration > ANIMATED_SCROLL_GAP)
			{
				int height = getHeight() - mPaddingBottom - mPaddingTop;
				int bottom = getChildAt(0).getHeight();
				int maxY = System.Math.Max(0, bottom - height);
				int scrollY = mScrollY;
				dy = System.Math.Max(0, System.Math.Min(scrollY + dy, maxY)) - scrollY;
				mScroller.startScroll(mScrollX, scrollY, 0, dy);
				invalidate();
			}
			else
			{
				if (!mScroller.isFinished())
				{
					mScroller.abortAnimation();
					if (mFlingStrictSpan != null)
					{
						mFlingStrictSpan.finish();
						mFlingStrictSpan = null;
					}
				}
				scrollBy(dx, dy);
			}
			mLastScroll = android.view.animation.AnimationUtils.currentAnimationTimeMillis();
		}