@@ -41,6 +41,13 @@ public interface Callback {
4141 private static final long EXPAND_DURATION = 250 ;
4242 private static final long GLOW_DURATION = 150 ;
4343
44+ // Set to false to disable focus-based gestures (two-finger pull).
45+ private static final boolean USE_DRAG = true ;
46+ // Set to false to disable scale-based gestures (both horizontal and vertical).
47+ private static final boolean USE_SPAN = true ;
48+ // Both gestures types may be active at the same time.
49+ // At least one gesture type should be active.
50+ // A variant of the screwdriver gesture will emerge from either gesture type.
4451
4552 // amount of overstretch for maximum brightness expressed in U
4653 // 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U
@@ -59,6 +66,7 @@ public interface Callback {
5966 private View mCurrViewBottomGlow ;
6067 private float mOldHeight ;
6168 private float mNaturalHeight ;
69+ private float mInitialTouchFocusY ;
6270 private float mInitialTouchSpan ;
6371 private Callback mCallback ;
6472 private ScaleGestureDetector mDetector ;
@@ -83,7 +91,7 @@ public void setHeight(float h) {
8391 ViewGroup .LayoutParams lp = mView .getLayoutParams ();
8492 lp .height = (int )h ;
8593 mView .setLayoutParams (lp );
86- mView .requestLayout ();
94+ mView .requestLayout ();
8795 }
8896 public float getHeight () {
8997 int height = mView .getLayoutParams ().height ;
@@ -94,15 +102,15 @@ public float getHeight() {
94102 }
95103 public int getNaturalHeight (int maximum ) {
96104 ViewGroup .LayoutParams lp = mView .getLayoutParams ();
97- if (DEBUG ) Log .v (TAG , "Inspecting a child of type: " + mView .getClass ().getName ());
105+ if (DEBUG ) Log .v (TAG , "Inspecting a child of type: " + mView .getClass ().getName ());
98106 int oldHeight = lp .height ;
99107 lp .height = ViewGroup .LayoutParams .WRAP_CONTENT ;
100108 mView .setLayoutParams (lp );
101109 mView .measure (
102110 View .MeasureSpec .makeMeasureSpec (mView .getMeasuredWidth (),
103- View .MeasureSpec .EXACTLY ),
111+ View .MeasureSpec .EXACTLY ),
104112 View .MeasureSpec .makeMeasureSpec (maximum ,
105- View .MeasureSpec .AT_MOST ));
113+ View .MeasureSpec .AT_MOST ));
106114 lp .height = oldHeight ;
107115 mView .setLayoutParams (lp );
108116 return mView .getMeasuredHeight ();
@@ -135,8 +143,9 @@ public boolean onScaleBegin(ScaleGestureDetector detector) {
135143 View v = mCallback .getChildAtPosition (detector .getFocusX (), detector .getFocusY ());
136144
137145 // your fingers have to be somewhat close to the bounds of the view in question
138- mInitialTouchSpan = Math .abs (detector .getCurrentSpanY ());
139- if (DEBUG ) Log .d (TAG , "got mInitialTouchSpan: " + mInitialTouchSpan );
146+ mInitialTouchFocusY = detector .getFocusY ();
147+ mInitialTouchSpan = Math .abs (detector .getCurrentSpan ());
148+ if (DEBUG ) Log .d (TAG , "got mInitialTouchSpan: (" + mInitialTouchSpan + ")" );
140149
141150 mStretching = initScale (v );
142151 return mStretching ;
@@ -145,16 +154,25 @@ public boolean onScaleBegin(ScaleGestureDetector detector) {
145154 @ Override
146155 public boolean onScale (ScaleGestureDetector detector ) {
147156 if (DEBUG ) Log .v (TAG , "onscale() on " + mCurrView );
148- float h = Math .abs (detector .getCurrentSpanY ());
149- if (DEBUG ) Log .d (TAG , "current span is: " + h );
150- h = h + mOldHeight - mInitialTouchSpan ;
151- float target = h ;
157+
158+ // are we scaling or dragging?
159+ float span = Math .abs (detector .getCurrentSpan ()) - mInitialTouchSpan ;
160+ span *= USE_SPAN ? 1f : 0f ;
161+ float drag = detector .getFocusY () - mInitialTouchFocusY ;
162+ drag *= USE_DRAG ? 1f : 0f ;
163+ float pull = Math .abs (drag ) + Math .abs (span ) + 1f ;
164+ float hand = drag * Math .abs (drag ) / pull + span * Math .abs (span ) / pull ;
165+ if (DEBUG ) Log .d (TAG , "current span handle is: " + hand );
166+ hand = hand + mOldHeight ;
167+ float target = hand ;
152168 if (DEBUG ) Log .d (TAG , "target is: " + target );
153- h = h <mSmallSize ?mSmallSize :(h >mLargeSize ?mLargeSize :h );
154- h = h >mNaturalHeight ?mNaturalHeight :h ;
155- if (DEBUG ) Log .d (TAG , "scale continues: h=" + h );
156- mScaler .setHeight (h );
157- float stretch = (float ) Math .abs ((target - h ) / mMaximumStretch );
169+ hand = hand < mSmallSize ? mSmallSize : (hand > mLargeSize ? mLargeSize : hand );
170+ hand = hand > mNaturalHeight ? mNaturalHeight : hand ;
171+ if (DEBUG ) Log .d (TAG , "scale continues: hand =" + hand );
172+ mScaler .setHeight (hand );
173+
174+ // glow if overscale
175+ float stretch = (float ) Math .abs ((target - hand ) / mMaximumStretch );
158176 float strength = 1f / (1f + (float ) Math .pow (Math .E , -1 * ((8f * stretch ) - 5f )));
159177 if (DEBUG ) Log .d (TAG , "stretch: " + stretch + " strength: " + strength );
160178 setGlow (GLOW_BASE + strength * (1f - GLOW_BASE ));
@@ -171,7 +189,10 @@ public void onScaleEnd(ScaleGestureDetector detector) {
171189 });
172190 }
173191 public void setGlow (float glow ) {
174- if (!mGlowAnimationSet .isRunning ()) {
192+ if (!mGlowAnimationSet .isRunning () || glow == 0f ) {
193+ if (mGlowAnimationSet .isRunning ()) {
194+ mGlowAnimationSet .cancel ();
195+ }
175196 if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null ) {
176197 if (glow == 0f || mCurrViewTopGlow .getAlpha () == 0f ) {
177198 // animate glow in and out
@@ -251,6 +272,7 @@ private void finishScale(boolean force) {
251272 mScaleAnimation .start ();
252273 mStretching = false ;
253274 setGlow (0f );
275+ if (DEBUG ) Log .d (TAG , "scale was finished on view: " + mCurrView );
254276 clearView ();
255277 }
256278
@@ -261,12 +283,12 @@ private void clearView() {
261283 }
262284
263285 private void setView (View v ) {
264- mCurrView = null ;
286+ mCurrView = v ;
265287 if (v instanceof ViewGroup ) {
266288 ViewGroup g = (ViewGroup ) v ;
267289 mCurrViewTopGlow = g .findViewById (R .id .top_glow );
268290 mCurrViewBottomGlow = g .findViewById (R .id .bottom_glow );
269- if (DEBUG ) {
291+ if (DEBUG ) {
270292 String debugLog = "Looking for glows: " +
271293 (mCurrViewTopGlow != null ? "found top " : "didn't find top" ) +
272294 (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom" );
0 commit comments