ExpandHelper.java revision 80a76276dc9440ffad30dc4c820eb7d65f4df368
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
206a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.animation.ObjectAnimator;
216a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.content.Context;
226a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.graphics.RectF;
236a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.util.Log;
246a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.MotionEvent;
256a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.ScaleGestureDetector;
266a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.View;
276a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.ViewGroup;
286a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport android.view.View.OnClickListener;
296a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerimport com.android.internal.widget.SizeAdaptiveLayout;
306a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
316a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandlerpublic class ExpandHelper implements Gefingerpoken, OnClickListener {
326a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    public interface Callback {
336a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        View getChildAtPosition(MotionEvent ev);
346a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        View getChildAtPosition(float x, float y);
3580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        boolean canChildBeExpanded(View v);
366a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
376a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
386a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private static final String TAG = "ExpandHelper";
396a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    protected static final boolean DEBUG = false;
406a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private static final long EXPAND_DURATION = 250;
416a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
4280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    // amount of overstretch for maximum brightness expressed in U
4380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    // 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U
4480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private static final float STRETCH_INTERVAL = 2f;
4580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren
4680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    // level of glow for a touch, without overstretch
4780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    // overstretch fills the range (GLOW_BASE, 1.0]
4880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private static final float GLOW_BASE = 0.5f;
4980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren
506a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    @SuppressWarnings("unused")
516a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private Context mContext;
526a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
536a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private boolean mStretching;
546a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private View mCurrView;
5580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private View mCurrViewTopGlow;
5680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private View mCurrViewBottomGlow;
576a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private float mOldHeight;
586a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private float mNaturalHeight;
596a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private float mInitialTouchSpan;
606a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private Callback mCallback;
616a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private ScaleGestureDetector mDetector;
626a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private ViewScaler mScaler;
636a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private ObjectAnimator mAnimation;
646a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
656a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private int mSmallSize;
666a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private int mLargeSize;
6780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private float mMaximumStretch;
686a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
696a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private class ViewScaler {
706a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        View mView;
716a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        public ViewScaler() {}
726a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        public void setView(View v) {
736a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mView = v;
746a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
756a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        public void setHeight(float h) {
7680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            if (DEBUG) Log.v(TAG, "SetHeight: setting to " + h);
776a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            ViewGroup.LayoutParams lp = mView.getLayoutParams();
786a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            lp.height = (int)h;
796a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mView.setLayoutParams(lp);
806a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler	    mView.requestLayout();
816a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
826a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        public float getHeight() {
836a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            int height = mView.getLayoutParams().height;
846a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            if (height < 0) {
856a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                height = mView.getMeasuredHeight();
866a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            }
876a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            return (float) height;
886a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
896a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        public int getNaturalHeight(int maximum) {
906a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            ViewGroup.LayoutParams lp = mView.getLayoutParams();
916a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler	    if (DEBUG) Log.v(TAG, "Inspecting a child of type: " + mView.getClass().getName());
926a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            int oldHeight = lp.height;
936a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
946a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mView.setLayoutParams(lp);
956a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mView.measure(
966a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                    View.MeasureSpec.makeMeasureSpec(mView.getMeasuredWidth(),
976a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler						     View.MeasureSpec.EXACTLY),
986a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                    View.MeasureSpec.makeMeasureSpec(maximum,
996a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler						     View.MeasureSpec.AT_MOST));
1006a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            lp.height = oldHeight;
1016a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mView.setLayoutParams(lp);
1026a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            return mView.getMeasuredHeight();
1036a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
1046a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
1056a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1066a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    public ExpandHelper(Context context, Callback callback, int small, int large) {
1076a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mSmallSize = small;
10880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        mMaximumStretch = mSmallSize * STRETCH_INTERVAL;
1096a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mLargeSize = large;
1106a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mContext = context;
1116a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mCallback = callback;
1126a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mScaler = new ViewScaler();
1136a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mDetector =
1146a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                new ScaleGestureDetector(context,
1156a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                                         new ScaleGestureDetector.SimpleOnScaleGestureListener() {
1166a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            @Override
1176a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            public boolean onScaleBegin(ScaleGestureDetector detector) {
1186a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.v(TAG, "onscalebegin()");
1196a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                View v = mCallback.getChildAtPosition(detector.getFocusX(), detector.getFocusY());
1206a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1216a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                // your fingers have to be somewhat close to the bounds of the view in question
1226a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                mInitialTouchSpan = Math.abs(detector.getCurrentSpanY());
1236a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.d(TAG, "got mInitialTouchSpan: " + mInitialTouchSpan);
1246a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1256a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                mStretching = initScale(v);
1266a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                return mStretching;
1276a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            }
1286a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1296a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            @Override
1306a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            public boolean onScale(ScaleGestureDetector detector) {
1316a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.v(TAG, "onscale() on " + mCurrView);
1326a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                float h = Math.abs(detector.getCurrentSpanY());
1336a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.d(TAG, "current span is: " + h);
1346a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                h = h + mOldHeight - mInitialTouchSpan;
13580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                float target = h;
13680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                if (DEBUG) Log.d(TAG, "target is: " + target);
1376a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                h = h<mSmallSize?mSmallSize:(h>mLargeSize?mLargeSize:h);
1386a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                h = h>mNaturalHeight?mNaturalHeight:h;
1396a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.d(TAG, "scale continues: h=" + h);
1406a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                mScaler.setHeight(h);
14180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                float stretch = (float) Math.abs((target - h) / mMaximumStretch);
14280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
14380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                if (DEBUG) Log.d(TAG, "stretch: " + stretch + " strength: " + strength);
14480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                setGlow(GLOW_BASE + strength * (1f - GLOW_BASE));
1456a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                return true;
1466a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            }
1476a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1486a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            @Override
1496a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            public void onScaleEnd(ScaleGestureDetector detector) {
1506a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.v(TAG, "onscaleend()");
1516a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                // I guess we're alone now
1526a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                if (DEBUG) Log.d(TAG, "scale end");
1536a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                finishScale(false);
1546a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            }
1556a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        });
1566a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
15780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    public void setGlow(float glow) {
15880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        if (mCurrViewTopGlow != null) {
15980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            mCurrViewTopGlow.setAlpha(glow);
16080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        }
16180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        if (mCurrViewBottomGlow != null) {
16280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            mCurrViewBottomGlow.setAlpha(glow);
16380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        }
16480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    }
1656a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1666a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    public boolean onInterceptTouchEvent(MotionEvent ev) {
1676a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        if (DEBUG) Log.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
1686a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                         " stretching=" + mStretching);
1696a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mDetector.onTouchEvent(ev);
1706a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        return mStretching;
1716a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
1726a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
1736a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    public boolean onTouchEvent(MotionEvent ev) {
1746a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        final int action = ev.getAction();
1756a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        if (DEBUG) Log.d(TAG, "touch: act=" + (action) + " stretching=" + mStretching);
1766a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        if (mStretching) {
1776a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mDetector.onTouchEvent(ev);
1786a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
1796a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        switch (action) {
1806a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            case MotionEvent.ACTION_UP:
1816a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            case MotionEvent.ACTION_CANCEL:
1826a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                mStretching = false;
18380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                clearView();
1846a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                break;
1856a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
1866a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        return true;
1876a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
1886a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private boolean initScale(View v) {
1896a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        if (v != null) {
1906a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            if (DEBUG) Log.d(TAG, "scale begins on view: " + v);
1916a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mStretching = true;
19280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            setView(v);
19380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            setGlow(GLOW_BASE);
1946a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mScaler.setView(v);
1956a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            mOldHeight = mScaler.getHeight();
19680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            if (mCallback.canChildBeExpanded(v)) {
19780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                if (DEBUG) Log.d(TAG, "working on an expandable child");
19880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
19980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            } else {
20080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                if (DEBUG) Log.d(TAG, "working on a non-expandable child");
20180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                mNaturalHeight = mOldHeight;
20280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            }
2036a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
2046a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler                        " mNaturalHeight: " + mNaturalHeight);
2056a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            v.getParent().requestDisallowInterceptTouchEvent(true);
2066a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
2076a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        return mStretching;
2086a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
2096a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
2106a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    private void finishScale(boolean force) {
2116a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        float h = mScaler.getHeight();
2126a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        final boolean wasClosed = (mOldHeight == mSmallSize);
2136a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        if (wasClosed) {
2146a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            h = (force || h > mSmallSize) ? mNaturalHeight : mSmallSize;
2156a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        } else {
2166a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler            h = (force || h < mNaturalHeight) ? mSmallSize : mNaturalHeight;
2176a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        }
21880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        if (DEBUG && mCurrView != null) mCurrView.setBackgroundColor(0);
2196a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mAnimation = ObjectAnimator.ofFloat(mScaler, "height", h).setDuration(EXPAND_DURATION);
2206a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mAnimation.start();
2216a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mStretching = false;
22280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        setGlow(0f);
22380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        clearView();
22480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    }
22580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren
22680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private void clearView() {
2276a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        mCurrView = null;
22880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        mCurrViewTopGlow = null;
22980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        mCurrViewBottomGlow = null;
23080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    }
23180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren
23280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren    private void setView(View v) {
23380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        mCurrView = null;
23480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        if (v instanceof ViewGroup) {
23580a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            ViewGroup g = (ViewGroup) v;
23680a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            mCurrViewTopGlow = g.findViewById(R.id.top_glow);
23780a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
23880a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren	    if (DEBUG) {
23980a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                String debugLog = "Looking for glows: " +
24080a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                        (mCurrViewTopGlow != null ? "found top " : "didn't find top") +
24180a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                        (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
24280a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren                Log.v(TAG,  debugLog);
24380a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren            }
24480a76276dc9440ffad30dc4c820eb7d65f4df368Chris Wren        }
2456a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
2466a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
2476a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    @Override
2486a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    public void onClick(View v) {
2496a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        initScale(v);
2506a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler        finishScale(true);
2516a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler
2526a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler    }
2536a858c347f4d4e5db4c8f00d5e285967631b71caDaniel Sandler}
254