diff options
| author | Adam Cohen <adamcohen@google.com> | 2010-08-18 22:20:31 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-08-18 22:20:31 -0700 |
| commit | 20b73ce9d14607fecc22cfeaa648737175c14d6a (patch) | |
| tree | d6a5a6813795f75af2c0c095b57d3e3850f76b3a /core/java | |
| parent | 2c5678d7b3f9811ca441f3720ce2c778fdaa0a6d (diff) | |
| parent | 3d07af03421f4727ef7e97c5c19e6ade50b19060 (diff) | |
| download | frameworks_base-20b73ce9d14607fecc22cfeaa648737175c14d6a.zip frameworks_base-20b73ce9d14607fecc22cfeaa648737175c14d6a.tar.gz frameworks_base-20b73ce9d14607fecc22cfeaa648737175c14d6a.tar.bz2 | |
Merge "-> Added edge behaviour for StackView (what to do at the beginning and end of the stack) -> Wrapping children of AdapterViewAnimator in a FrameLayout to uphold the Adapter contract (ie. don't modify the Adapter's views.) -> Fixed clipping problem in StackViews with padding"
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/widget/AdapterViewAnimator.java | 17 | ||||
| -rw-r--r-- | core/java/android/widget/StackView.java | 156 |
2 files changed, 127 insertions, 46 deletions
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java index f11c5c6..b6c8e47 100644 --- a/core/java/android/widget/AdapterViewAnimator.java +++ b/core/java/android/widget/AdapterViewAnimator.java @@ -340,9 +340,14 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> for (int i = 0; i < mPreviousViews.size(); i++) { View viewToRemove = mPreviousViews.get(i); viewToRemove.clearAnimation(); + if (viewToRemove instanceof ViewGroup) { + ViewGroup vg = (ViewGroup) viewToRemove; + vg.removeAllViewsInLayout(); + } // applyTransformForChildAtIndex here just allows for any cleanup // associated with this view that may need to be done by a subclass applyTransformForChildAtIndex(viewToRemove, -1); + removeViewInLayout(viewToRemove); } mPreviousViews.clear(); @@ -405,10 +410,14 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> // and apply any transform / animation View newView = mAdapter.getView(i, null, this); if (newView != null) { - mActiveViews[index] = newView; - addViewInLayout(newView, -1, createOrReuseLayoutParams(newView)); - applyTransformForChildAtIndex(newView, newRelativeIndex); - animateViewForTransition(-1, newRelativeIndex, newView); + // We wrap the new view in a FrameLayout so as to respect the contract + // with the adapter, that is, that we don't modify this view directly + FrameLayout fl = new FrameLayout(mContext); + fl.addView(newView); + mActiveViews[index] = fl; + addViewInLayout(fl, -1, createOrReuseLayoutParams(fl)); + applyTransformForChildAtIndex(fl, newRelativeIndex); + animateViewForTransition(-1, newRelativeIndex, fl); } } mActiveViews[index].bringToFront(); diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index 5797cbb..c3e8838 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -48,7 +48,7 @@ public class StackView extends AdapterViewAnimator { /** * Default animation parameters */ - private final int DEFAULT_ANIMATION_DURATION = 500; + private final int DEFAULT_ANIMATION_DURATION = 400; private final int MINIMUM_ANIMATION_DURATION = 50; /** @@ -141,9 +141,9 @@ public class StackView extends AdapterViewAnimator { view.setVisibility(VISIBLE); LayoutParams lp = (LayoutParams) view.getLayoutParams(); + int largestDuration = + Math.round(mStackSlider.getDurationForNeutralPosition()*DEFAULT_ANIMATION_DURATION); - int largestDuration = Math.round( - (lp.verticalOffset*1.0f/-mViewHeight)*DEFAULT_ANIMATION_DURATION); int duration = largestDuration; if (mYVelocity != 0) { duration = 1000*(0 - lp.verticalOffset)/Math.abs(mYVelocity); @@ -165,7 +165,8 @@ public class StackView extends AdapterViewAnimator { // Slide item out LayoutParams lp = (LayoutParams) view.getLayoutParams(); - int largestDuration = Math.round(mStackSlider.getYProgress()*DEFAULT_ANIMATION_DURATION); + int largestDuration = Math.round(mStackSlider.getDurationForOffscreenPosition()* + DEFAULT_ANIMATION_DURATION); int duration = largestDuration; if (mYVelocity != 0) { duration = 1000*(lp.verticalOffset + mViewHeight)/Math.abs(mYVelocity); @@ -245,6 +246,7 @@ public class StackView extends AdapterViewAnimator { // ClipChildren and ClipToPadding. We're probably going to want to reset // these flags as well. setClipChildren(false); + setClipToPadding(false); ViewGroup view = this; while (view.getParent() != null && view.getParent() instanceof ViewGroup) { view = (ViewGroup) view.getParent(); @@ -297,22 +299,37 @@ public class StackView extends AdapterViewAnimator { private void beginGestureIfNeeded(float deltaY) { if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) { - mSwipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; + int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; cancelLongPress(); requestDisallowInterceptTouchEvent(true); - int activeIndex = mSwipeGestureType == GESTURE_SLIDE_DOWN ? mNumActiveViews - 1 + int activeIndex = swipeGestureType == GESTURE_SLIDE_DOWN ? mNumActiveViews - 1 : mNumActiveViews - 2; - View v = getViewAtRelativeIndex(activeIndex); - if (v != null) { - mHighlight.setImageBitmap(createOutline(v)); - mHighlight.bringToFront(); - v.bringToFront(); - mStackSlider.setView(v); - if (mSwipeGestureType == GESTURE_SLIDE_DOWN) - v.setVisibility(VISIBLE); + if (mAdapter == null) return; + + if (mCurrentWindowStartUnbounded + activeIndex == 0) { + mStackSlider.setMode(StackSlider.BEGINNING_OF_STACK_MODE); + } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount()) { + activeIndex--; + mStackSlider.setMode(StackSlider.END_OF_STACK_MODE); + } else { + mStackSlider.setMode(StackSlider.NORMAL_MODE); } + + View v = getViewAtRelativeIndex(activeIndex); + if (v == null) return; + + mHighlight.setImageBitmap(createOutline(v)); + mHighlight.bringToFront(); + v.bringToFront(); + mStackSlider.setView(v); + + if (swipeGestureType == GESTURE_SLIDE_DOWN) + v.setVisibility(VISIBLE); + + // We only register this gesture if we've made it this far without a problem + mSwipeGestureType = swipeGestureType; } } @@ -339,7 +356,7 @@ public class StackView extends AdapterViewAnimator { case MotionEvent.ACTION_MOVE: { beginGestureIfNeeded(deltaY); - float rx = 0.3f*deltaX/(mViewHeight*1.0f); + float rx = deltaX/(mViewHeight*1.0f); if (mSwipeGestureType == GESTURE_SLIDE_DOWN) { float r = (deltaY-mTouchSlop*1.0f)/mViewHeight*1.0f; mStackSlider.setYProgress(1 - r); @@ -351,7 +368,6 @@ public class StackView extends AdapterViewAnimator { mStackSlider.setXProgress(rx); return true; } - break; } case MotionEvent.ACTION_UP: { @@ -412,7 +428,7 @@ public class StackView extends AdapterViewAnimator { } } // if we made it this far, it means we didn't find a satisfactory new pointer :(, - // so end the + // so end the gesture handlePointerUp(ev); } } @@ -422,25 +438,30 @@ public class StackView extends AdapterViewAnimator { float newY = ev.getY(pointerIndex); int deltaY = (int) (newY - mInitialY); - mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); - mYVelocity = (int) mVelocityTracker.getYVelocity(mActivePointerId); + if (mVelocityTracker != null) { + mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + mYVelocity = (int) mVelocityTracker.getYVelocity(mActivePointerId); + } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } - if (deltaY > mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_DOWN) { + if (deltaY > mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_DOWN + && mStackSlider.mMode == StackSlider.NORMAL_MODE) { // Swipe threshold exceeded, swipe down showNext(); mHighlight.bringToFront(); - } else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP) { + } else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP + && mStackSlider.mMode == StackSlider.NORMAL_MODE) { // Swipe threshold exceeded, swipe up showPrevious(); mHighlight.bringToFront(); } else if (mSwipeGestureType == GESTURE_SLIDE_UP) { // Didn't swipe up far enough, snap back down - int duration = Math.round(mStackSlider.getYProgress()*DEFAULT_ANIMATION_DURATION); + int duration = + Math.round(mStackSlider.getDurationForNeutralPosition()*DEFAULT_ANIMATION_DURATION); StackSlider animationSlider = new StackSlider(mStackSlider); PropertyAnimator snapBackY = new PropertyAnimator(duration, animationSlider, @@ -453,8 +474,9 @@ public class StackView extends AdapterViewAnimator { snapBackX.start(); } else if (mSwipeGestureType == GESTURE_SLIDE_DOWN) { // Didn't swipe down far enough, snap back up - int duration = Math.round((1 - - mStackSlider.getYProgress())*DEFAULT_ANIMATION_DURATION); + int duration = Math.round(mStackSlider.getDurationForOffscreenPosition()* + DEFAULT_ANIMATION_DURATION); + StackSlider animationSlider = new StackSlider(mStackSlider); PropertyAnimator snapBackY = new PropertyAnimator(duration, animationSlider, "YProgress", mStackSlider.getYProgress(), 1); @@ -475,6 +497,12 @@ public class StackView extends AdapterViewAnimator { float mYProgress; float mXProgress; + static final int NORMAL_MODE = 0; + static final int BEGINNING_OF_STACK_MODE = 1; + static final int END_OF_STACK_MODE = 2; + + int mMode = NORMAL_MODE; + public StackSlider() { } @@ -482,6 +510,7 @@ public class StackView extends AdapterViewAnimator { mView = copy.mView; mYProgress = copy.mYProgress; mXProgress = copy.mXProgress; + mMode = copy.mMode; } private float cubic(float r) { @@ -525,43 +554,85 @@ public class StackView extends AdapterViewAnimator { r = Math.max(0, r); mYProgress = r; - final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams(); final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams(); - viewLp.setVerticalOffset(Math.round(-r*mViewHeight)); - highlightLp.setVerticalOffset(Math.round(-r*mViewHeight)); - mHighlight.setAlpha(highlightAlphaInterpolator(r)); - - float alpha = viewAlphaInterpolator(1-r); + switch (mMode) { + case NORMAL_MODE: + viewLp.setVerticalOffset(Math.round(-r*mViewHeight)); + highlightLp.setVerticalOffset(Math.round(-r*mViewHeight)); + mHighlight.setAlpha(highlightAlphaInterpolator(r)); + + float alpha = viewAlphaInterpolator(1-r); + + // We make sure that views which can't be seen (have 0 alpha) are also invisible + // so that they don't interfere with click events. + if (mView.getAlpha() == 0 && alpha != 0 && mView.getVisibility() != VISIBLE) { + mView.setVisibility(VISIBLE); + } else if (alpha == 0 && mView.getAlpha() != 0 + && mView.getVisibility() == VISIBLE) { + mView.setVisibility(INVISIBLE); + } - // We make sure that views which can't be seen (have 0 alpha) are also invisible - // so that they don't interfere with click events. - if (mView.getAlpha() == 0 && alpha != 0 && mView.getVisibility() != VISIBLE) { - mView.setVisibility(VISIBLE); - } else if (alpha == 0 && mView.getAlpha() != 0 && mView.getVisibility() == VISIBLE) { - mView.setVisibility(INVISIBLE); + mView.setAlpha(alpha); + mView.setRotationX(90.0f*rotationInterpolator(r)); + mHighlight.setRotationX(90.0f*rotationInterpolator(r)); + break; + case BEGINNING_OF_STACK_MODE: + r = r*0.2f; + viewLp.setVerticalOffset(Math.round(-r*mViewHeight)); + highlightLp.setVerticalOffset(Math.round(-r*mViewHeight)); + mHighlight.setAlpha(highlightAlphaInterpolator(r)); + break; + case END_OF_STACK_MODE: + r = (1-r)*0.2f; + viewLp.setVerticalOffset(Math.round(r*mViewHeight)); + highlightLp.setVerticalOffset(Math.round(r*mViewHeight)); + mHighlight.setAlpha(highlightAlphaInterpolator(r)); + break; } - - mView.setAlpha(viewAlphaInterpolator(1-r)); - mView.setRotationX(90.0f*rotationInterpolator(r)); - mHighlight.setRotationX(90.0f*rotationInterpolator(r)); } public void setXProgress(float r) { // enforce r between 0 and 1 - r = Math.min(1.0f, r); - r = Math.max(-1.0f, r); + r = Math.min(2.0f, r); + r = Math.max(-2.0f, r); mXProgress = r; final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams(); final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams(); + r *= 0.2f; viewLp.setHorizontalOffset(Math.round(r*mViewHeight)); highlightLp.setHorizontalOffset(Math.round(r*mViewHeight)); } + void setMode(int mode) { + mMode = mode; + } + + float getDurationForNeutralPosition() { + return getDuration(false); + } + + float getDurationForOffscreenPosition() { + return getDuration(mMode == END_OF_STACK_MODE ? false : true); + } + + private float getDuration(boolean invert) { + if (mView != null) { + final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams(); + + float d = (float) Math.sqrt(Math.pow(viewLp.horizontalOffset,2) + + Math.pow(viewLp.verticalOffset,2)); + float maxd = (float) Math.sqrt(Math.pow(mViewHeight, 2) + + Math.pow(0.4f*mViewHeight, 2)); + return invert ? (1-d/maxd) : d/maxd; + } + return 0; + } + float getYProgress() { return mYProgress; } @@ -569,6 +640,7 @@ public class StackView extends AdapterViewAnimator { float getXProgress() { return mXProgress; } + } @Override |
