1640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell/*
2640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * Copyright (C) 2011 The Android Open Source Project
3640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell *
4640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * you may not use this file except in compliance with the License.
6640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * You may obtain a copy of the License at
7640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell *
8640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell *
10640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * Unless required by applicable law or agreed to in writing, software
11640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * See the License for the specific language governing permissions and
14640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell * limitations under the License.
15640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell */
16640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellpackage com.android.internal.widget;
17640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
18425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powellimport com.android.internal.R;
193d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
203d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viveretteimport android.util.TypedValue;
213d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viveretteimport android.view.ContextThemeWrapper;
2282d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viveretteimport android.view.MotionEvent;
23fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport android.widget.ActionMenuPresenter;
24fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport android.widget.ActionMenuView;
25640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
26640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.animation.Animator;
27640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.animation.AnimatorSet;
28640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.animation.ObjectAnimator;
29640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.animation.TimeInterpolator;
30640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.content.Context;
31425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powellimport android.content.res.Configuration;
32425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powellimport android.content.res.TypedArray;
33640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.util.AttributeSet;
34640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.view.View;
35640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.view.ViewGroup;
36640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.view.animation.DecelerateInterpolator;
37640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
38640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellpublic abstract class AbsActionBarView extends ViewGroup {
393d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
403d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
413d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    private static final int FADE_DURATION = 200;
423d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
433d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
443d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
453d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /** Context against which to inflate popup menus. */
463d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    protected final Context mPopupContext;
473d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
48640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected ActionMenuView mMenuView;
498d02deabac62c4a68a335a7b3141795466362b89Adam Powell    protected ActionMenuPresenter mActionMenuPresenter;
50e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    protected ViewGroup mSplitView;
51a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    protected boolean mSplitActionBar;
52a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    protected boolean mSplitWhenNarrow;
53425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    protected int mContentHeight;
54640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
55640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected Animator mVisibilityAnim;
56640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
5782d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    private boolean mEatingTouch;
5882d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    private boolean mEatingHover;
5982d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
60640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public AbsActionBarView(Context context) {
61d6479ec5eec13914f656f6be996d95fe1610fd57Alan Viverette        this(context, null);
62640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
63640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
64640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public AbsActionBarView(Context context, AttributeSet attrs) {
65d6479ec5eec13914f656f6be996d95fe1610fd57Alan Viverette        this(context, attrs, 0);
66640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
67640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
68617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public AbsActionBarView(Context context, AttributeSet attrs, int defStyleAttr) {
69617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
70617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    }
71617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette
72617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public AbsActionBarView(
73617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
74617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
753d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
763d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        final TypedValue tv = new TypedValue();
773d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        if (context.getTheme().resolveAttribute(R.attr.actionBarPopupTheme, tv, true)
783d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                && tv.resourceId != 0) {
793d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mPopupContext = new ContextThemeWrapper(context, tv.resourceId);
803d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        } else {
813d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mPopupContext = context;
823d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        }
83640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
84640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
85425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    @Override
86425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    protected void onConfigurationChanged(Configuration newConfig) {
87425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        super.onConfigurationChanged(newConfig);
88425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell
89425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        // Action bar can change size on configuration changes.
90425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        // Reread the desired height from the theme-specified style.
91425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
92425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell                com.android.internal.R.attr.actionBarStyle, 0);
93425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
94425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        a.recycle();
95a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell        if (mSplitWhenNarrow) {
96e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell            setSplitToolbar(getContext().getResources().getBoolean(
97a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell                    com.android.internal.R.bool.split_action_bar_is_narrow));
98a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell        }
99425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        if (mActionMenuPresenter != null) {
100425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell            mActionMenuPresenter.onConfigurationChanged(newConfig);
101425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        }
102425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    }
103425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell
10482d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    @Override
10582d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    public boolean onTouchEvent(MotionEvent ev) {
10682d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        // ActionBarViews always eat touch events, but should still respect the touch event dispatch
10782d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        // contract. If the normal View implementation doesn't want the events, we'll just silently
10882d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        // eat the rest of the gesture without reporting the events to the default implementation
10982d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        // since that's what it expects.
11082d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
11182d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        final int action = ev.getActionMasked();
11282d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        if (action == MotionEvent.ACTION_DOWN) {
11382d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            mEatingTouch = false;
11482d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        }
11582d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
11682d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        if (!mEatingTouch) {
11782d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            final boolean handled = super.onTouchEvent(ev);
11882d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            if (action == MotionEvent.ACTION_DOWN && !handled) {
11982d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette                mEatingTouch = true;
12082d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            }
12182d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        }
12282d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
12382d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
12482d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            mEatingTouch = false;
12582d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        }
12682d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
12782d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        return true;
12882d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    }
12982d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
13082d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    @Override
13182d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    public boolean onHoverEvent(MotionEvent ev) {
13282d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        // Same deal as onTouchEvent() above. Eat all hover events, but still
13382d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        // respect the touch event dispatch contract.
13482d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
13582d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        final int action = ev.getActionMasked();
13682d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        if (action == MotionEvent.ACTION_HOVER_ENTER) {
13782d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            mEatingHover = false;
13882d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        }
13982d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
14082d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        if (!mEatingHover) {
14182d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            final boolean handled = super.onHoverEvent(ev);
14282d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            if (action == MotionEvent.ACTION_HOVER_ENTER && !handled) {
14382d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette                mEatingHover = true;
14482d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            }
14582d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        }
14682d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
14782d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        if (action == MotionEvent.ACTION_HOVER_EXIT
14882d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette                || action == MotionEvent.ACTION_CANCEL) {
14982d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette            mEatingHover = false;
15082d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        }
15182d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
15282d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette        return true;
15382d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette    }
15482d31d456e3b727bcf45a58710b4ea91f69c049aAlan Viverette
155a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    /**
156a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell     * Sets whether the bar should be split right now, no questions asked.
157a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell     * @param split true if the bar should split
158a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell     */
159e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public void setSplitToolbar(boolean split) {
160a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell        mSplitActionBar = split;
161a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    }
162a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell
163a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    /**
164a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell     * Sets whether the bar should split if we enter a narrow screen configuration.
165a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell     * @param splitWhenNarrow true if the bar should check to split after a config change
166a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell     */
167a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    public void setSplitWhenNarrow(boolean splitWhenNarrow) {
168a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell        mSplitWhenNarrow = splitWhenNarrow;
169a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell    }
170a05aba9c506cd12a753c53e060c289095c3477e9Adam Powell
171425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    public void setContentHeight(int height) {
172425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        mContentHeight = height;
173425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        requestLayout();
174425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    }
175425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell
176425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    public int getContentHeight() {
177425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell        return mContentHeight;
178425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell    }
179425689eea2f4f208f29b944b4973981bdbeda9f5Adam Powell
180e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public void setSplitView(ViewGroup splitView) {
181640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        mSplitView = splitView;
182640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
183640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
1849a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell    /**
1859a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell     * @return Current visibility or if animating, the visibility being animated to.
1869a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell     */
1879a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell    public int getAnimatedVisibility() {
1889a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell        if (mVisibilityAnim != null) {
1899a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell            return mVisAnimListener.mFinalVisibility;
1909a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell        }
1919a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell        return getVisibility();
1929a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell    }
1939a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell
19494283533aba1b8c895728feb40462250a1ebecceDoris Liu    public Animator setupAnimatorToVisibility(int visibility, long duration) {
195640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        if (mVisibilityAnim != null) {
196640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mVisibilityAnim.cancel();
197640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
19894283533aba1b8c895728feb40462250a1ebecceDoris Liu
199640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        if (visibility == VISIBLE) {
200640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (getVisibility() != VISIBLE) {
201640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                setAlpha(0);
202640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (mSplitView != null && mMenuView != null) {
203640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    mMenuView.setAlpha(0);
204640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
205640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
20694283533aba1b8c895728feb40462250a1ebecceDoris Liu            ObjectAnimator anim = ObjectAnimator.ofFloat(this, View.ALPHA, 1);
20794283533aba1b8c895728feb40462250a1ebecceDoris Liu            anim.setDuration(duration);
208640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            anim.setInterpolator(sAlphaInterpolator);
209640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (mSplitView != null && mMenuView != null) {
210640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                AnimatorSet set = new AnimatorSet();
21194283533aba1b8c895728feb40462250a1ebecceDoris Liu                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, View.ALPHA, 1);
21294283533aba1b8c895728feb40462250a1ebecceDoris Liu                splitAnim.setDuration(duration);
213640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                set.addListener(mVisAnimListener.withFinalVisibility(visibility));
214640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                set.play(anim).with(splitAnim);
21594283533aba1b8c895728feb40462250a1ebecceDoris Liu                return set;
216640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            } else {
217640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
21894283533aba1b8c895728feb40462250a1ebecceDoris Liu                return anim;
219640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
220640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        } else {
22194283533aba1b8c895728feb40462250a1ebecceDoris Liu            ObjectAnimator anim = ObjectAnimator.ofFloat(this, View.ALPHA, 0);
22294283533aba1b8c895728feb40462250a1ebecceDoris Liu            anim.setDuration(duration);
223640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            anim.setInterpolator(sAlphaInterpolator);
224640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (mSplitView != null && mMenuView != null) {
225640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                AnimatorSet set = new AnimatorSet();
22694283533aba1b8c895728feb40462250a1ebecceDoris Liu                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, View.ALPHA, 0);
22794283533aba1b8c895728feb40462250a1ebecceDoris Liu                splitAnim.setDuration(duration);
228640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                set.addListener(mVisAnimListener.withFinalVisibility(visibility));
229640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                set.play(anim).with(splitAnim);
23094283533aba1b8c895728feb40462250a1ebecceDoris Liu                return set;
231640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            } else {
232640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
23394283533aba1b8c895728feb40462250a1ebecceDoris Liu                return anim;
234640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
235640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
236640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
237640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
23894283533aba1b8c895728feb40462250a1ebecceDoris Liu    public void animateToVisibility(int visibility) {
23994283533aba1b8c895728feb40462250a1ebecceDoris Liu        Animator anim = setupAnimatorToVisibility(visibility, FADE_DURATION);
24094283533aba1b8c895728feb40462250a1ebecceDoris Liu        anim.start();
24194283533aba1b8c895728feb40462250a1ebecceDoris Liu    }
24294283533aba1b8c895728feb40462250a1ebecceDoris Liu
243640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
244640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public void setVisibility(int visibility) {
2459caeb145721238897809805f521bb5c8ef375c0fGeorge Mount        if (visibility != getVisibility()) {
2469caeb145721238897809805f521bb5c8ef375c0fGeorge Mount            if (mVisibilityAnim != null) {
2479caeb145721238897809805f521bb5c8ef375c0fGeorge Mount                mVisibilityAnim.end();
2489caeb145721238897809805f521bb5c8ef375c0fGeorge Mount            }
2499caeb145721238897809805f521bb5c8ef375c0fGeorge Mount            super.setVisibility(visibility);
250640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
251640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
252640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
253640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public boolean showOverflowMenu() {
2548d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (mActionMenuPresenter != null) {
2558d02deabac62c4a68a335a7b3141795466362b89Adam Powell            return mActionMenuPresenter.showOverflowMenu();
256640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
257640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        return false;
258640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
259640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
260640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public void postShowOverflowMenu() {
261640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        post(new Runnable() {
262640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            public void run() {
263640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                showOverflowMenu();
264640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
265640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        });
266640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
267640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
268640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public boolean hideOverflowMenu() {
2698d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (mActionMenuPresenter != null) {
2708d02deabac62c4a68a335a7b3141795466362b89Adam Powell            return mActionMenuPresenter.hideOverflowMenu();
271640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
272640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        return false;
273640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
274640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
275640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public boolean isOverflowMenuShowing() {
2768d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (mActionMenuPresenter != null) {
2778d02deabac62c4a68a335a7b3141795466362b89Adam Powell            return mActionMenuPresenter.isOverflowMenuShowing();
278640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
279640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        return false;
280640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
281640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
2825fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell    public boolean isOverflowMenuShowPending() {
2835fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell        if (mActionMenuPresenter != null) {
2845fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell            return mActionMenuPresenter.isOverflowMenuShowPending();
2855fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell        }
2865fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell        return false;
2875fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell    }
2885fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell
289640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public boolean isOverflowReserved() {
2908d02deabac62c4a68a335a7b3141795466362b89Adam Powell        return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
291640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
292640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
293e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean canShowOverflowMenu() {
294e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return isOverflowReserved() && getVisibility() == VISIBLE;
295e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
296e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
297640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public void dismissPopupMenus() {
2988d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (mActionMenuPresenter != null) {
2998d02deabac62c4a68a335a7b3141795466362b89Adam Powell            mActionMenuPresenter.dismissPopupMenus();
300640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
301640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
302640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
303640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected int measureChildView(View child, int availableWidth, int childSpecHeight,
304640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            int spacing) {
305640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
306640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                childSpecHeight);
307640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
308640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        availableWidth -= child.getMeasuredWidth();
309640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        availableWidth -= spacing;
310640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
3115d4034a37e5ac3832b91388024f6eddf343cf3f6Adam Powell        return Math.max(0, availableWidth);
312640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
313640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
314cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio    static protected int next(int x, int val, boolean isRtl) {
315cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio        return isRtl ? x - val : x + val;
316640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
317640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
318cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio    protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
319640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int childWidth = child.getMeasuredWidth();
320640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int childHeight = child.getMeasuredHeight();
321640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int childTop = y + (contentHeight - childHeight) / 2;
322640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
323cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio        if (reverse) {
324cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio            child.layout(x - childWidth, childTop, x, childTop + childHeight);
325cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio        } else {
326cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio            child.layout(x, childTop, x + childWidth, childTop + childHeight);
327cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio        }
328640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
329cf1ba0298c48ae56608ed556dc715eb69c54f9b9Fabrice Di Meglio        return  (reverse ? -childWidth : childWidth);
330640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
331640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
332640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected class VisibilityAnimListener implements Animator.AnimatorListener {
333640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        private boolean mCanceled = false;
3349a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell        int mFinalVisibility;
335640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
336640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public VisibilityAnimListener withFinalVisibility(int visibility) {
337640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mFinalVisibility = visibility;
338640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            return this;
339640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
340640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
341640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @Override
342640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public void onAnimationStart(Animator animation) {
343640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            setVisibility(VISIBLE);
344640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mVisibilityAnim = animation;
345640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mCanceled = false;
346640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
347640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
348640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @Override
349640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public void onAnimationEnd(Animator animation) {
350640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (mCanceled) return;
351640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
352640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mVisibilityAnim = null;
353640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            setVisibility(mFinalVisibility);
3549a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell            if (mSplitView != null && mMenuView != null) {
3559a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell                mMenuView.setVisibility(mFinalVisibility);
3569a5cc2810bbbcb0eab4579aa4131039820d92101Adam Powell            }
357640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
358640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
359640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @Override
360640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public void onAnimationCancel(Animator animation) {
361640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mCanceled = true;
362640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
363640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
364640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @Override
365640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public void onAnimationRepeat(Animator animation) {
366640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
367640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
368640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell}
369