@@ -87,6 +87,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
8787 private int mDragHandleSize ; // handle hitrect extension into the challenge view
8888 private int mDragHandleHeadroom ; // extend the handle's hitrect this far above the line
8989 private int mDragHandleEdgeSlop ;
90+ private int mChallengeBottomBound ; // Number of pixels from the top of the challenge view
91+ // that should remain on-screen
9092 float mHandleAlpha ;
9193 float mFrameAlpha ;
9294 private ObjectAnimator mHandleAnimation ;
@@ -228,11 +230,14 @@ public SlidingChallengeLayout(Context context, AttributeSet attrs, int defStyle)
228230 public void setDragDrawables (Drawable handle , Drawable icon ) {
229231 final float density = getResources ().getDisplayMetrics ().density ;
230232 final int defaultSize = (int ) (DRAG_HANDLE_DEFAULT_SIZE * density + 0.5f );
231- mDragHandleSize = Math .max (handle != null ? handle .getIntrinsicHeight () : defaultSize ,
232- icon != null ? icon .getIntrinsicHeight () : defaultSize );
233+ final int handleHeight = handle != null ? handle .getIntrinsicHeight () : 0 ;
234+ final int iconHeight = icon != null ? icon .getIntrinsicHeight () : 0 ;
235+ mDragHandleSize = Math .max (handleHeight > 0 ? handleHeight : defaultSize ,
236+ iconHeight > 0 ? iconHeight : defaultSize );
233237
234238 // top half of the lock icon, plus another 25% to be sure
235- mDragHandleHeadroom = (icon != null ) ? (int )(icon .getIntrinsicHeight () * 0.75f ) : 0 ;
239+ mDragHandleHeadroom = (int ) (iconHeight * 0.75f );
240+ mChallengeBottomBound = (mDragHandleSize + mDragHandleHeadroom + handleHeight ) / 2 ;
236241
237242 mHandleDrawable = handle ;
238243 mDragIconDrawable = icon ;
@@ -258,8 +263,13 @@ public void showHandle(boolean visible) {
258263 void animateHandle (boolean visible ) {
259264 if (mHandleAnimation != null ) {
260265 mHandleAnimation .cancel ();
266+ mHandleAnimation = null ;
261267 }
262- mHandleAnimation = ObjectAnimator .ofFloat (this , HANDLE_ALPHA , visible ? 1.f : 0.f );
268+ final float targetAlpha = visible ? 1.f : 0.f ;
269+ if (targetAlpha == mHandleAlpha ) {
270+ return ;
271+ }
272+ mHandleAnimation = ObjectAnimator .ofFloat (this , HANDLE_ALPHA , targetAlpha );
263273 mHandleAnimation .setInterpolator (sHandleFadeInterpolator );
264274 mHandleAnimation .setDuration (HANDLE_ANIMATE_DURATION );
265275 mHandleAnimation .start ();
@@ -270,9 +280,14 @@ void animateFrame(boolean visible, boolean full) {
270280
271281 if (mFrameAnimation != null ) {
272282 mFrameAnimation .cancel ();
283+ mFrameAnimation = null ;
284+ }
285+ final float targetAlpha = visible ? (full ? 1.f : 0.5f ) : 0.f ;
286+ if (targetAlpha == mFrameAlpha ) {
287+ return ;
273288 }
274- mFrameAnimation = ObjectAnimator . ofFloat ( this , FRAME_ALPHA ,
275- visible ? ( full ? 1.f : 0.5f ) : 0.f );
289+
290+ mFrameAnimation = ObjectAnimator . ofFloat ( this , FRAME_ALPHA , targetAlpha );
276291 mFrameAnimation .setInterpolator (sHandleFadeInterpolator );
277292 mFrameAnimation .setDuration (HANDLE_ANIMATE_DURATION );
278293 mFrameAnimation .start ();
@@ -337,7 +352,7 @@ void setScrollState(int state) {
337352 mScrollState = state ;
338353
339354 animateHandle (state == SCROLL_STATE_IDLE && !mChallengeShowing );
340- animateFrame (state == SCROLL_STATE_DRAGGING , false );
355+ animateFrame (state != SCROLL_STATE_IDLE , false );
341356 if (mScrollListener != null ) {
342357 mScrollListener .onScrollStateChanged (state );
343358 }
@@ -370,8 +385,8 @@ void animateChallengeTo(int y, int velocity) {
370385 // Nothing to do.
371386 return ;
372387 }
373- int sy = mChallengeView .getBottom ();
374- int dy = y - sy ;
388+ final int sy = mChallengeView .getBottom ();
389+ final int dy = y - sy ;
375390 if (dy == 0 ) {
376391 completeChallengeScroll ();
377392 return ;
@@ -400,12 +415,7 @@ void animateChallengeTo(int y, int velocity) {
400415 }
401416
402417 private void setChallengeShowing (boolean showChallenge ) {
403- if (mChallengeShowing != showChallenge ) {
404- mChallengeShowing = showChallenge ;
405- if (mChallengeView != null ) {
406- mChallengeView .setVisibility (showChallenge ? VISIBLE : INVISIBLE );
407- }
408- }
418+ mChallengeShowing = showChallenge ;
409419 }
410420
411421 /**
@@ -576,7 +586,7 @@ public boolean onTouchEvent(MotionEvent ev) {
576586 }
577587 final float y = ev .getY (index );
578588 final float pos = Math .min (y - mGestureStartY ,
579- getChallengeOpenedTop () );
589+ getLayoutBottom () - mChallengeBottomBound );
580590
581591 moveChallengeTo (mGestureStartChallengeBottom + (int ) pos );
582592 }
@@ -648,7 +658,6 @@ protected void onMeasure(int widthSpec, int heightSpec) {
648658 }
649659 // We're going to play silly games with the frame's background drawable later.
650660 mFrameDrawable = mChallengeView .getBackground ();
651- mFrameDrawable .setAlpha (0 );
652661 } else if (lp .childType == LayoutParams .CHILD_TYPE_SCRIM ) {
653662 setScrimView (child );
654663 }
@@ -686,10 +695,9 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
686695 final int layoutBottom = height - paddingBottom - lp .bottomMargin ;
687696 // We use the top of the challenge view to position the handle, so
688697 // we never want less than the handle size showing at the bottom.
689- final int bottom = layoutBottom + (int ) ((childHeight - mDragHandleSize )
698+ final int bottom = layoutBottom + (int ) ((childHeight - mChallengeBottomBound )
690699 * (1 - mChallengeOffset ));
691- float offset = 1.f - (bottom - layoutBottom ) / childHeight ;
692- child .setAlpha (offset );
700+ child .setAlpha (mChallengeOffset / 2 + 0.5f );
693701 child .layout (left , bottom - childHeight , left + childWidth , bottom );
694702 } else {
695703 // Non-challenge views lay out from the upper left, layered.
@@ -709,6 +717,9 @@ public void run() {
709717 sendInitialListenerUpdates ();
710718 }
711719 });
720+ if (mFrameDrawable != null ) {
721+ mFrameDrawable .setAlpha (0 );
722+ }
712723 mHasLayout = true ;
713724 }
714725 }
@@ -803,9 +814,10 @@ private boolean moveChallengeTo(int bottom) {
803814 final int challengeHeight = mChallengeView .getHeight ();
804815
805816 bottom = Math .max (layoutBottom ,
806- Math .min (bottom , layoutBottom + challengeHeight - mDragHandleSize ));
817+ Math .min (bottom , layoutBottom + challengeHeight - mChallengeBottomBound ));
807818
808- float offset = 1.f - (float ) (bottom - layoutBottom ) / (challengeHeight - mDragHandleSize );
819+ float offset = 1.f - (float ) (bottom - layoutBottom ) /
820+ (challengeHeight - mChallengeBottomBound );
809821 mChallengeOffset = offset ;
810822 if (offset > 0 && !mChallengeShowing ) {
811823 setChallengeShowing (true );
@@ -814,7 +826,7 @@ private boolean moveChallengeTo(int bottom) {
814826 mChallengeView .layout (mChallengeView .getLeft (),
815827 bottom - mChallengeView .getHeight (), mChallengeView .getRight (), bottom );
816828
817- mChallengeView .setAlpha (offset );
829+ mChallengeView .setAlpha (offset / 2 + 0.5f );
818830 if (mScrollListener != null ) {
819831 mScrollListener .onScrollPositionChanged (offset , mChallengeView .getTop ());
820832 }
@@ -850,10 +862,6 @@ private int getChallengeOpenedTop() {
850862 return getLayoutBottom () - ((mChallengeView == null ) ? 0 : mChallengeView .getHeight ());
851863 }
852864
853- private void moveChallengeBy (int delta ) {
854- moveChallengeTo (getChallengeBottom () + delta );
855- }
856-
857865 /**
858866 * Show or hide the challenge view, animating it if necessary.
859867 * @param show true to show, false to hide
@@ -879,10 +887,9 @@ private void showChallenge(boolean show, int velocity) {
879887 }
880888
881889 if (mHasLayout ) {
882- final int bottomMargin = ((LayoutParams ) mChallengeView .getLayoutParams ()).bottomMargin ;
883- final int layoutBottom = getHeight () - getPaddingBottom () - bottomMargin ;
890+ final int layoutBottom = getLayoutBottom ();
884891 animateChallengeTo (show ? layoutBottom :
885- layoutBottom + mChallengeView .getHeight () - mDragHandleSize , velocity );
892+ layoutBottom + mChallengeView .getHeight () - mChallengeBottomBound , velocity );
886893 }
887894 }
888895
0 commit comments