@@ -22,6 +22,7 @@ public final void LOG(String fmt, Object... args) {
2222 }
2323
2424 public static final boolean BRAKES = false ;
25+ private static final boolean STRETCH_PAST_CONTENTS = true ;
2526
2627 private float mSelfExpandVelocityPx ; // classic value: 2000px/s
2728 private float mSelfCollapseVelocityPx ; // classic value: 2000px/s (will be negated to collapse "up")
@@ -45,6 +46,9 @@ public final void LOG(String fmt, Object... args) {
4546 private float mTouchOffset ;
4647 private float mExpandedFraction = 0 ;
4748 private float mExpandedHeight = 0 ;
49+ private boolean mClosing ;
50+ private boolean mRubberbanding ;
51+ private boolean mTracking ;
4852
4953 private TimeAnimator mTimeAnimator ;
5054 private VelocityTracker mVelocityTracker ;
@@ -61,12 +65,13 @@ public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime)
6165
6266 private final Runnable mStopAnimator = new Runnable () { public void run () {
6367 if (mTimeAnimator .isStarted ()) {
64- mTimeAnimator .end (); }
68+ mTimeAnimator .end ();
69+ }
6570 }};
6671
6772 private float mVel , mAccel ;
6873 private int mFullHeight = 0 ;
69- private String mViewName ;
74+ private String mViewName ;
7075
7176 private void animationTick (long dtms ) {
7277 if (!mTimeAnimator .isStarted ()) {
@@ -75,53 +80,59 @@ private void animationTick(long dtms) {
7580 mTimeAnimator .setTimeListener (mAnimationCallback );
7681
7782 mTimeAnimator .start ();
83+
84+ mRubberbanding = STRETCH_PAST_CONTENTS && mExpandedHeight > getFullHeight ();
85+ mClosing = (mExpandedHeight > 0 && mVel < 0 ) || mRubberbanding ;
7886 } else if (dtms > 0 ) {
7987 final float dt = dtms * 0.001f ; // ms -> s
8088 LOG ("tick: v=%.2fpx/s dt=%.4fs" , mVel , dt );
8189 LOG ("tick: before: h=%d" , (int ) mExpandedHeight );
8290
8391 final float fh = getFullHeight ();
84- final boolean closing = mExpandedHeight > 0 && mVel < 0 ;
8592 boolean braking = false ;
8693 if (BRAKES ) {
87- if (closing ) {
94+ if (mClosing ) {
8895 braking = mExpandedHeight <= mCollapseBrakingDistancePx ;
8996 mAccel = braking ? 10 *mCollapseAccelPx : -mCollapseAccelPx ;
9097 } else {
9198 braking = mExpandedHeight >= (fh -mExpandBrakingDistancePx );
9299 mAccel = braking ? 10 *-mExpandAccelPx : mExpandAccelPx ;
93100 }
94101 } else {
95- mAccel = closing ? -mCollapseAccelPx : mExpandAccelPx ;
102+ mAccel = mClosing ? -mCollapseAccelPx : mExpandAccelPx ;
96103 }
97104
98105 mVel += mAccel * dt ;
99106
100107 if (braking ) {
101- if (closing && mVel > -mBrakingSpeedPx ) {
108+ if (mClosing && mVel > -mBrakingSpeedPx ) {
102109 mVel = -mBrakingSpeedPx ;
103- } else if (!closing && mVel < mBrakingSpeedPx ) {
110+ } else if (!mClosing && mVel < mBrakingSpeedPx ) {
104111 mVel = mBrakingSpeedPx ;
105112 }
106113 } else {
107- if (closing && mVel > -mFlingCollapseMinVelocityPx ) {
114+ if (mClosing && mVel > -mFlingCollapseMinVelocityPx ) {
108115 mVel = -mFlingCollapseMinVelocityPx ;
109- } else if (!closing && mVel > mFlingGestureMaxOutputVelocityPx ) {
116+ } else if (!mClosing && mVel > mFlingGestureMaxOutputVelocityPx ) {
110117 mVel = mFlingGestureMaxOutputVelocityPx ;
111118 }
112119 }
113120
114121 float h = mExpandedHeight + mVel * dt ;
122+
123+ if (mRubberbanding && h < fh ) {
124+ h = fh ;
125+ }
115126
116- LOG ("tick: new h=%d closing=%s" , (int ) h , closing ?"true" :"false" );
127+ LOG ("tick: new h=%d closing=%s" , (int ) h , mClosing ?"true" :"false" );
117128
118129 setExpandedHeightInternal (h );
119130
120131 mBar .panelExpansionChanged (PanelView .this , mExpandedFraction );
121132
122133 if (mVel == 0
123- || (closing && mExpandedHeight == 0 )
124- || (! closing && mExpandedHeight == getFullHeight () )) {
134+ || (mClosing && mExpandedHeight == 0 )
135+ || (( mRubberbanding || ! mClosing ) && mExpandedHeight == fh )) {
125136 post (mStopAnimator );
126137 }
127138 }
@@ -183,14 +194,15 @@ public boolean onTouch(View v, MotionEvent event) {
183194
184195 switch (event .getAction ()) {
185196 case MotionEvent .ACTION_DOWN :
197+ mTracking = true ;
186198 mVelocityTracker = VelocityTracker .obtain ();
187199 trackMovement (event );
188200 mBar .onTrackingStarted (PanelView .this );
189201 mTouchOffset = (rawY - mAbsPos [1 ]) - PanelView .this .getExpandedHeight ();
190202 break ;
191203
192204 case MotionEvent .ACTION_MOVE :
193- PanelView .this .setExpandedHeight (rawY - mAbsPos [1 ] - mTouchOffset );
205+ PanelView .this .setExpandedHeightInternal (rawY - mAbsPos [1 ] - mTouchOffset );
194206
195207 mBar .panelExpansionChanged (PanelView .this , mExpandedFraction );
196208
@@ -199,6 +211,7 @@ public boolean onTouch(View v, MotionEvent event) {
199211
200212 case MotionEvent .ACTION_UP :
201213 case MotionEvent .ACTION_CANCEL :
214+ mTracking = false ;
202215 mBar .onTrackingStopped (PanelView .this );
203216 trackMovement (event );
204217 mVelocityTracker .computeCurrentVelocity (1000 );
@@ -275,6 +288,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
275288 LOG ("onMeasure(%d, %d) -> (%d, %d)" ,
276289 widthMeasureSpec , heightMeasureSpec , getMeasuredWidth (), getMeasuredHeight ());
277290 mFullHeight = getMeasuredHeight ();
291+ // if one of our children is getting smaller, we should track that
292+ if (!mTracking && !mRubberbanding && !mTimeAnimator .isStarted () && mExpandedHeight > 0 && mExpandedHeight != mFullHeight ) {
293+ mExpandedHeight = mFullHeight ;
294+ }
278295 heightMeasureSpec = MeasureSpec .makeMeasureSpec (
279296 (int ) mExpandedHeight , MeasureSpec .AT_MOST ); // MeasureSpec.getMode(heightMeasureSpec));
280297 setMeasuredDimension (widthMeasureSpec , heightMeasureSpec );
@@ -286,17 +303,22 @@ public void setExpandedHeight(float height) {
286303 setExpandedHeightInternal (height );
287304 }
288305
306+ @ Override
307+ protected void onLayout (boolean changed , int left , int top , int right , int bottom ) {
308+ LOG ("onLayout: changed=%s, bottom=%d eh=%d fh=%d" , changed ?"T" :"f" , bottom , (int )mExpandedHeight , (int )mFullHeight );
309+ super .onLayout (changed , left , top , right , bottom );
310+ }
311+
289312 public void setExpandedHeightInternal (float h ) {
290313 float fh = getFullHeight ();
291314 if (fh == 0 ) {
292315 // Hmm, full height hasn't been computed yet
293316 }
294317
295- LOG ("setExpansion: height=%.1f fh=%.1f" , h , fh );
318+ LOG ("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s " , h , fh , mTracking ? "T" : "f" , mRubberbanding ? "T" : "f" );
296319
297320 if (h < 0 ) h = 0 ;
298- else if (h > fh ) h = fh ;
299-
321+ if (!(STRETCH_PAST_CONTENTS && (mTracking || mRubberbanding )) && h > fh ) h = fh ;
300322 mExpandedHeight = h ;
301323
302324 requestLayout ();
0 commit comments