Methods Summary |
---|
public boolean | canChildBeDismissed(android.view.View v)
return true;
|
android.view.MotionEvent | createMotionEventForStackScroll(android.view.MotionEvent ev)Constructs a simulated motion event for the current stack scroll.
MotionEvent pev = MotionEvent.obtainNoHistory(ev);
pev.setLocation(0, mScroller.progressToScrollRange(mScroller.getStackScroll()));
return pev;
|
TaskView | findViewAtPoint(int x, int y)Returns the view at the specified coordinates
int childCount = mSv.getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) mSv.getChildAt(i);
if (tv.getVisibility() == View.VISIBLE) {
if (mSv.isTransformedTouchPointInView(x, y, tv)) {
return tv;
}
}
}
return null;
|
public android.view.View | getChildAtPosition(android.view.MotionEvent ev)SwipeHelper Implementation
return findViewAtPoint((int) ev.getX(), (int) ev.getY());
|
void | initOrResetVelocityTracker()Velocity tracker helpers
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
} else {
mVelocityTracker.clear();
}
|
void | initVelocityTrackerIfNotExists()
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
|
public void | onBeginDrag(android.view.View v)
TaskView tv = (TaskView) v;
// Disable clipping with the stack while we are swiping
tv.setClipViewInStack(false);
// Disallow touch events from this task view
tv.setTouchEnabled(false);
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
|
public void | onChildDismissed(android.view.View v)
TaskView tv = (TaskView) v;
// Re-enable clipping with the stack (we will reuse this view)
tv.setClipViewInStack(true);
// Re-enable touch events from this task view
tv.setTouchEnabled(true);
// Remove the task view from the stack
mSv.onTaskViewDismissed(tv);
|
public void | onDragCancelled(android.view.View v)
// Do nothing
|
public boolean | onGenericMotionEvent(android.view.MotionEvent ev)Handles generic motion events
if ((ev.getSource() & InputDevice.SOURCE_CLASS_POINTER) ==
InputDevice.SOURCE_CLASS_POINTER) {
int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_SCROLL:
// Find the front most task and scroll the next task to the front
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vScroll > 0) {
if (mSv.ensureFocusedTask()) {
mSv.focusNextTask(true, false);
}
} else {
if (mSv.ensureFocusedTask()) {
mSv.focusNextTask(false, false);
}
}
return true;
}
}
return false;
|
public boolean | onInterceptTouchEvent(android.view.MotionEvent ev)Touch preprocessing for handling below
// Return early if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
return false;
}
// Pass through to swipe helper if we are swiping
mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
if (mInterceptedBySwipeHelper) {
return true;
}
boolean wasScrolling = mScroller.isScrolling() ||
(mScroller.mScrollAnimator != null && mScroller.mScrollAnimator.isRunning());
int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
// Save the touch down info
mInitialMotionX = mLastMotionX = (int) ev.getX();
mInitialMotionY = mLastMotionY = (int) ev.getY();
mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
mActivePointerId = ev.getPointerId(0);
mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
// Stop the current scroll if it is still flinging
mScroller.stopScroller();
mScroller.stopBoundScrollAnimation();
// Initialize the velocity tracker
initOrResetVelocityTracker();
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
break;
}
case MotionEvent.ACTION_MOVE: {
if (mActivePointerId == INACTIVE_POINTER_ID) break;
// Initialize the velocity tracker if necessary
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int y = (int) ev.getY(activePointerIndex);
int x = (int) ev.getX(activePointerIndex);
if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
// Save the touch move info
mIsScrolling = true;
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
mLastMotionX = x;
mLastMotionY = y;
mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// Animate the scroll back if we've cancelled
mScroller.animateBoundScroll();
// Reset the drag state and the velocity tracker
mIsScrolling = false;
mActivePointerId = INACTIVE_POINTER_ID;
mActiveTaskView = null;
mTotalPMotion = 0;
recycleVelocityTracker();
break;
}
}
return wasScrolling || mIsScrolling;
|
public void | onSnapBackCompleted(android.view.View v)
TaskView tv = (TaskView) v;
// Re-enable clipping with the stack
tv.setClipViewInStack(true);
// Re-enable touch events from this task view
tv.setTouchEnabled(true);
|
public void | onSwipeChanged(android.view.View v, float delta)
// Do nothing
|
public boolean | onTouchEvent(android.view.MotionEvent ev)Handles touch events once we have intercepted them
// Short circuit if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
return false;
}
// Pass through to swipe helper if we are swiping
if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
return true;
}
// Update the velocity tracker
initVelocityTrackerIfNotExists();
int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
// Save the touch down info
mInitialMotionX = mLastMotionX = (int) ev.getX();
mInitialMotionY = mLastMotionY = (int) ev.getY();
mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
mActivePointerId = ev.getPointerId(0);
mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
// Stop the current scroll if it is still flinging
mScroller.stopScroller();
mScroller.stopBoundScrollAnimation();
// Initialize the velocity tracker
initOrResetVelocityTracker();
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
final int index = ev.getActionIndex();
mActivePointerId = ev.getPointerId(index);
mLastMotionX = (int) ev.getX(index);
mLastMotionY = (int) ev.getY(index);
mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
break;
}
case MotionEvent.ACTION_MOVE: {
if (mActivePointerId == INACTIVE_POINTER_ID) break;
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int x = (int) ev.getX(activePointerIndex);
int y = (int) ev.getY(activePointerIndex);
int yTotal = Math.abs(y - mInitialMotionY);
float curP = mSv.mLayoutAlgorithm.screenYToCurveProgress(y);
float deltaP = mLastP - curP;
if (!mIsScrolling) {
if (yTotal > mScrollTouchSlop) {
mIsScrolling = true;
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
}
if (mIsScrolling) {
float curStackScroll = mScroller.getStackScroll();
float overScrollAmount = mScroller.getScrollAmountOutOfBounds(curStackScroll + deltaP);
if (Float.compare(overScrollAmount, 0f) != 0) {
// Bound the overscroll to a fixed amount, and inversely scale the y-movement
// relative to how close we are to the max overscroll
float maxOverScroll = mConfig.taskStackOverscrollPct;
deltaP *= (1f - (Math.min(maxOverScroll, overScrollAmount)
/ maxOverScroll));
}
mScroller.setStackScroll(curStackScroll + deltaP);
}
mLastMotionX = x;
mLastMotionY = y;
mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
mTotalPMotion += Math.abs(deltaP);
break;
}
case MotionEvent.ACTION_UP: {
mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocity = (int) mVelocityTracker.getYVelocity(mActivePointerId);
if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
float overscrollRangePct = Math.abs((float) velocity / mMaximumVelocity);
int overscrollRange = (int) (Math.min(1f, overscrollRangePct) *
(Constants.Values.TaskStackView.TaskStackMaxOverscrollRange -
Constants.Values.TaskStackView.TaskStackMinOverscrollRange));
mScroller.mScroller.fling(0,
mScroller.progressToScrollRange(mScroller.getStackScroll()),
0, velocity,
0, 0,
mScroller.progressToScrollRange(mSv.mLayoutAlgorithm.mMinScrollP),
mScroller.progressToScrollRange(mSv.mLayoutAlgorithm.mMaxScrollP),
0, Constants.Values.TaskStackView.TaskStackMinOverscrollRange +
overscrollRange);
// Invalidate to kick off computeScroll
mSv.invalidate();
} else if (mScroller.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
mScroller.animateBoundScroll();
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
mTotalPMotion = 0;
recycleVelocityTracker();
break;
}
case MotionEvent.ACTION_POINTER_UP: {
int pointerIndex = ev.getActionIndex();
int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// Select a new active pointer id and reset the motion state
final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
mLastMotionX = (int) ev.getX(newPointerIndex);
mLastMotionY = (int) ev.getY(newPointerIndex);
mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
mVelocityTracker.clear();
}
break;
}
case MotionEvent.ACTION_CANCEL: {
if (mScroller.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
mScroller.animateBoundScroll();
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
mTotalPMotion = 0;
recycleVelocityTracker();
break;
}
}
return true;
|
void | recycleVelocityTracker()
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
|