ExpandHelper.java revision 8fd12657e353a4a6f6d875a0d86850426fec00e8
16a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler/* 26a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * Copyright (C) 2012 The Android Open Source Project 36a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * 46a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 56a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * you may not use this file except in compliance with the License. 66a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * You may obtain a copy of the License at 76a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * 86a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 96a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * 106a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * Unless required by applicable law or agreed to in writing, software 116a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 126a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * See the License for the specific language governing permissions and 146a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler * limitations under the License. 156a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler */ 166a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 176a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 186a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerpackage com.android.systemui; 196a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 20ba925e8ecd9decff5701001a0190042d6797942dChris Wrenimport android.animation.AnimatorSet; 216a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.animation.ObjectAnimator; 226a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.content.Context; 236a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.graphics.RectF; 246a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.util.Log; 256a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.MotionEvent; 266a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.ScaleGestureDetector; 276a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.View; 286a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.ViewGroup; 296a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.View.OnClickListener; 306a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport com.android.internal.widget.SizeAdaptiveLayout; 316a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 326a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerpublic class ExpandHelper implements Gefingerpoken, OnClickListener { 336a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public interface Callback { 346a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler View getChildAtPosition(MotionEvent ev); 356a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler View getChildAtPosition(float x, float y); 3680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren boolean canChildBeExpanded(View v); 378fd12657e353a4a6f6d875a0d86850426fec00e8Chris Wren boolean setUserExpandedChild(View v, boolean userxpanded); 386a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 396a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 406a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private static final String TAG = "ExpandHelper"; 416a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler protected static final boolean DEBUG = false; 426a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private static final long EXPAND_DURATION = 250; 43ba925e8ecd9decff5701001a0190042d6797942dChris Wren private static final long GLOW_DURATION = 150; 44ba925e8ecd9decff5701001a0190042d6797942dChris Wren 4589139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // Set to false to disable focus-based gestures (two-finger pull). 4689139d74b27305a29ca082c75d94dcbed5f84625Chris Wren private static final boolean USE_DRAG = true; 4789139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // Set to false to disable scale-based gestures (both horizontal and vertical). 4889139d74b27305a29ca082c75d94dcbed5f84625Chris Wren private static final boolean USE_SPAN = true; 4989139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // Both gestures types may be active at the same time. 5089139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // At least one gesture type should be active. 5189139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // A variant of the screwdriver gesture will emerge from either gesture type. 526a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 5380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren // amount of overstretch for maximum brightness expressed in U 5480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren // 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U 5580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private static final float STRETCH_INTERVAL = 2f; 5680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren 5780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren // level of glow for a touch, without overstretch 5880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren // overstretch fills the range (GLOW_BASE, 1.0] 5980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private static final float GLOW_BASE = 0.5f; 6080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren 616a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler @SuppressWarnings("unused") 626a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private Context mContext; 636a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 646a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private boolean mStretching; 656a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private View mCurrView; 6680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private View mCurrViewTopGlow; 6780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private View mCurrViewBottomGlow; 686a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private float mOldHeight; 696a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private float mNaturalHeight; 7089139d74b27305a29ca082c75d94dcbed5f84625Chris Wren private float mInitialTouchFocusY; 716a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private float mInitialTouchSpan; 726a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private Callback mCallback; 736a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private ScaleGestureDetector mDetector; 746a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private ViewScaler mScaler; 75ba925e8ecd9decff5701001a0190042d6797942dChris Wren private ObjectAnimator mScaleAnimation; 76ba925e8ecd9decff5701001a0190042d6797942dChris Wren private AnimatorSet mGlowAnimationSet; 77ba925e8ecd9decff5701001a0190042d6797942dChris Wren private ObjectAnimator mGlowTopAnimation; 78ba925e8ecd9decff5701001a0190042d6797942dChris Wren private ObjectAnimator mGlowBottomAnimation; 796a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 806a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private int mSmallSize; 816a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private int mLargeSize; 8280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private float mMaximumStretch; 836a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 846a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private class ViewScaler { 856a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler View mView; 866a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public ViewScaler() {} 876a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public void setView(View v) { 886a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mView = v; 896a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 906a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public void setHeight(float h) { 9180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (DEBUG) Log.v(TAG, "SetHeight: setting to " + h); 926a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler ViewGroup.LayoutParams lp = mView.getLayoutParams(); 936a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler lp.height = (int)h; 946a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mView.setLayoutParams(lp); 9589139d74b27305a29ca082c75d94dcbed5f84625Chris Wren mView.requestLayout(); 966a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 976a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public float getHeight() { 986a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler int height = mView.getLayoutParams().height; 996a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (height < 0) { 1006a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler height = mView.getMeasuredHeight(); 1016a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1026a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return (float) height; 1036a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1046a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public int getNaturalHeight(int maximum) { 1056a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler ViewGroup.LayoutParams lp = mView.getLayoutParams(); 10689139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (DEBUG) Log.v(TAG, "Inspecting a child of type: " + mView.getClass().getName()); 1076a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler int oldHeight = lp.height; 1086a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; 1096a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mView.setLayoutParams(lp); 1106a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mView.measure( 1116a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler View.MeasureSpec.makeMeasureSpec(mView.getMeasuredWidth(), 11289139d74b27305a29ca082c75d94dcbed5f84625Chris Wren View.MeasureSpec.EXACTLY), 1136a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler View.MeasureSpec.makeMeasureSpec(maximum, 11489139d74b27305a29ca082c75d94dcbed5f84625Chris Wren View.MeasureSpec.AT_MOST)); 1156a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler lp.height = oldHeight; 1166a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mView.setLayoutParams(lp); 1176a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return mView.getMeasuredHeight(); 1186a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1196a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1206a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 1216a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public ExpandHelper(Context context, Callback callback, int small, int large) { 1226a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mSmallSize = small; 12380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mMaximumStretch = mSmallSize * STRETCH_INTERVAL; 1246a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mLargeSize = large; 1256a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mContext = context; 1266a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mCallback = callback; 1276a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mScaler = new ViewScaler(); 128ba925e8ecd9decff5701001a0190042d6797942dChris Wren 129ba925e8ecd9decff5701001a0190042d6797942dChris Wren mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f); 130ba925e8ecd9decff5701001a0190042d6797942dChris Wren mScaleAnimation.setDuration(EXPAND_DURATION); 131ba925e8ecd9decff5701001a0190042d6797942dChris Wren 132ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowTopAnimation = ObjectAnimator.ofFloat(null, "alpha", 0f); 133ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowBottomAnimation = ObjectAnimator.ofFloat(null, "alpha", 0f); 134ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowAnimationSet = new AnimatorSet(); 135ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowAnimationSet.play(mGlowTopAnimation).with(mGlowBottomAnimation); 136ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowAnimationSet.setDuration(GLOW_DURATION); 137ba925e8ecd9decff5701001a0190042d6797942dChris Wren 1386a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mDetector = 1396a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler new ScaleGestureDetector(context, 1406a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler new ScaleGestureDetector.SimpleOnScaleGestureListener() { 1416a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler @Override 1426a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public boolean onScaleBegin(ScaleGestureDetector detector) { 1436a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.v(TAG, "onscalebegin()"); 1446a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler View v = mCallback.getChildAtPosition(detector.getFocusX(), detector.getFocusY()); 1456a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 1466a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler // your fingers have to be somewhat close to the bounds of the view in question 14789139d74b27305a29ca082c75d94dcbed5f84625Chris Wren mInitialTouchFocusY = detector.getFocusY(); 14889139d74b27305a29ca082c75d94dcbed5f84625Chris Wren mInitialTouchSpan = Math.abs(detector.getCurrentSpan()); 14989139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (DEBUG) Log.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")"); 1506a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 1516a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mStretching = initScale(v); 1526a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return mStretching; 1536a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1546a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 1556a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler @Override 1566a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public boolean onScale(ScaleGestureDetector detector) { 1576a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.v(TAG, "onscale() on " + mCurrView); 15889139d74b27305a29ca082c75d94dcbed5f84625Chris Wren 15989139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // are we scaling or dragging? 16089139d74b27305a29ca082c75d94dcbed5f84625Chris Wren float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan; 16189139d74b27305a29ca082c75d94dcbed5f84625Chris Wren span *= USE_SPAN ? 1f : 0f; 16289139d74b27305a29ca082c75d94dcbed5f84625Chris Wren float drag = detector.getFocusY() - mInitialTouchFocusY; 16389139d74b27305a29ca082c75d94dcbed5f84625Chris Wren drag *= USE_DRAG ? 1f : 0f; 16489139d74b27305a29ca082c75d94dcbed5f84625Chris Wren float pull = Math.abs(drag) + Math.abs(span) + 1f; 16589139d74b27305a29ca082c75d94dcbed5f84625Chris Wren float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull; 16689139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (DEBUG) Log.d(TAG, "current span handle is: " + hand); 16789139d74b27305a29ca082c75d94dcbed5f84625Chris Wren hand = hand + mOldHeight; 16889139d74b27305a29ca082c75d94dcbed5f84625Chris Wren float target = hand; 16980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (DEBUG) Log.d(TAG, "target is: " + target); 17089139d74b27305a29ca082c75d94dcbed5f84625Chris Wren hand = hand < mSmallSize ? mSmallSize : (hand > mLargeSize ? mLargeSize : hand); 17189139d74b27305a29ca082c75d94dcbed5f84625Chris Wren hand = hand > mNaturalHeight ? mNaturalHeight : hand; 17289139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (DEBUG) Log.d(TAG, "scale continues: hand =" + hand); 17389139d74b27305a29ca082c75d94dcbed5f84625Chris Wren mScaler.setHeight(hand); 17489139d74b27305a29ca082c75d94dcbed5f84625Chris Wren 17589139d74b27305a29ca082c75d94dcbed5f84625Chris Wren // glow if overscale 17689139d74b27305a29ca082c75d94dcbed5f84625Chris Wren float stretch = (float) Math.abs((target - hand) / mMaximumStretch); 17780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f))); 17880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (DEBUG) Log.d(TAG, "stretch: " + stretch + " strength: " + strength); 17980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren setGlow(GLOW_BASE + strength * (1f - GLOW_BASE)); 1806a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return true; 1816a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1826a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 1836a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler @Override 1846a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public void onScaleEnd(ScaleGestureDetector detector) { 1856a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.v(TAG, "onscaleend()"); 1866a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler // I guess we're alone now 1876a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.d(TAG, "scale end"); 1886a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler finishScale(false); 1896a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 1906a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler }); 1916a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 19280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren public void setGlow(float glow) { 19389139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (!mGlowAnimationSet.isRunning() || glow == 0f) { 19489139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (mGlowAnimationSet.isRunning()) { 19589139d74b27305a29ca082c75d94dcbed5f84625Chris Wren mGlowAnimationSet.cancel(); 19689139d74b27305a29ca082c75d94dcbed5f84625Chris Wren } 197ba925e8ecd9decff5701001a0190042d6797942dChris Wren if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null) { 198ba925e8ecd9decff5701001a0190042d6797942dChris Wren if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) { 199ba925e8ecd9decff5701001a0190042d6797942dChris Wren // animate glow in and out 200ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowTopAnimation.setTarget(mCurrViewTopGlow); 201ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowBottomAnimation.setTarget(mCurrViewBottomGlow); 202ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowTopAnimation.setFloatValues(glow); 203ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowBottomAnimation.setFloatValues(glow); 204ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowAnimationSet.setupStartValues(); 205ba925e8ecd9decff5701001a0190042d6797942dChris Wren mGlowAnimationSet.start(); 206ba925e8ecd9decff5701001a0190042d6797942dChris Wren } else { 207ba925e8ecd9decff5701001a0190042d6797942dChris Wren // set it explicitly in reponse to touches. 208ba925e8ecd9decff5701001a0190042d6797942dChris Wren mCurrViewTopGlow.setAlpha(glow); 209ba925e8ecd9decff5701001a0190042d6797942dChris Wren mCurrViewBottomGlow.setAlpha(glow); 210ba925e8ecd9decff5701001a0190042d6797942dChris Wren } 211ba925e8ecd9decff5701001a0190042d6797942dChris Wren } 21280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 21380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 2146a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 2156a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public boolean onInterceptTouchEvent(MotionEvent ev) { 2166a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.d(TAG, "interceptTouch: act=" + (ev.getAction()) + 2176a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler " stretching=" + mStretching); 2186a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mDetector.onTouchEvent(ev); 2196a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return mStretching; 2206a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 2216a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 2226a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public boolean onTouchEvent(MotionEvent ev) { 2236a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler final int action = ev.getAction(); 2246a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.d(TAG, "touch: act=" + (action) + " stretching=" + mStretching); 2256a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (mStretching) { 2266a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mDetector.onTouchEvent(ev); 2276a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 2286a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler switch (action) { 2296a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler case MotionEvent.ACTION_UP: 2306a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler case MotionEvent.ACTION_CANCEL: 2316a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mStretching = false; 23280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren clearView(); 2336a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler break; 2346a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 2356a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return true; 2366a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 2376a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private boolean initScale(View v) { 2386a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (v != null) { 2396a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.d(TAG, "scale begins on view: " + v); 2406a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mStretching = true; 24180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren setView(v); 24280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren setGlow(GLOW_BASE); 2436a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mScaler.setView(v); 2446a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mOldHeight = mScaler.getHeight(); 24580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (mCallback.canChildBeExpanded(v)) { 24680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (DEBUG) Log.d(TAG, "working on an expandable child"); 24780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mNaturalHeight = mScaler.getNaturalHeight(mLargeSize); 24880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } else { 24980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (DEBUG) Log.d(TAG, "working on a non-expandable child"); 25080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mNaturalHeight = mOldHeight; 25180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 2526a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight + 2536a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler " mNaturalHeight: " + mNaturalHeight); 2546a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler v.getParent().requestDisallowInterceptTouchEvent(true); 2556a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 2566a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler return mStretching; 2576a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 2586a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 2596a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler private void finishScale(boolean force) { 2606a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler float h = mScaler.getHeight(); 2616a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler final boolean wasClosed = (mOldHeight == mSmallSize); 2626a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler if (wasClosed) { 2636a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler h = (force || h > mSmallSize) ? mNaturalHeight : mSmallSize; 2646a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } else { 2656a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler h = (force || h < mNaturalHeight) ? mSmallSize : mNaturalHeight; 2666a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 26780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (DEBUG && mCurrView != null) mCurrView.setBackgroundColor(0); 268ba925e8ecd9decff5701001a0190042d6797942dChris Wren if (mScaleAnimation.isRunning()) { 269ba925e8ecd9decff5701001a0190042d6797942dChris Wren mScaleAnimation.cancel(); 270ba925e8ecd9decff5701001a0190042d6797942dChris Wren } 271ba925e8ecd9decff5701001a0190042d6797942dChris Wren mScaleAnimation.setFloatValues(h); 272ba925e8ecd9decff5701001a0190042d6797942dChris Wren mScaleAnimation.setupStartValues(); 273ba925e8ecd9decff5701001a0190042d6797942dChris Wren mScaleAnimation.start(); 2746a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mStretching = false; 27580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren setGlow(0f); 2768fd12657e353a4a6f6d875a0d86850426fec00e8Chris Wren mCallback.setUserExpandedChild(mCurrView, h == mNaturalHeight); 27789139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (DEBUG) Log.d(TAG, "scale was finished on view: " + mCurrView); 27880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren clearView(); 27980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 28080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren 28180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private void clearView() { 2826a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler mCurrView = null; 28380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mCurrViewTopGlow = null; 28480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mCurrViewBottomGlow = null; 28580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 28680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren 28780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren private void setView(View v) { 28889139d74b27305a29ca082c75d94dcbed5f84625Chris Wren mCurrView = v; 28980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren if (v instanceof ViewGroup) { 29080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren ViewGroup g = (ViewGroup) v; 29180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mCurrViewTopGlow = g.findViewById(R.id.top_glow); 29280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow); 29389139d74b27305a29ca082c75d94dcbed5f84625Chris Wren if (DEBUG) { 29480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren String debugLog = "Looking for glows: " + 29580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren (mCurrViewTopGlow != null ? "found top " : "didn't find top") + 29680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom"); 29780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren Log.v(TAG, debugLog); 29880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 29980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren } 3006a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 3016a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 3026a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler @Override 3036a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler public void onClick(View v) { 3046a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler initScale(v); 3056a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler finishScale(true); 3066a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler 3076a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler } 3086a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler} 309