AbsActionBarView.java revision fa18d182a3f37505940e73ae6cd76c2e939f7f7c
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.internal.widget;
17
18import com.android.internal.R;
19import android.widget.ActionMenuPresenter;
20import android.widget.ActionMenuView;
21
22import android.animation.Animator;
23import android.animation.AnimatorSet;
24import android.animation.ObjectAnimator;
25import android.animation.TimeInterpolator;
26import android.content.Context;
27import android.content.res.Configuration;
28import android.content.res.TypedArray;
29import android.util.AttributeSet;
30import android.view.View;
31import android.view.ViewGroup;
32import android.view.animation.DecelerateInterpolator;
33
34public abstract class AbsActionBarView extends ViewGroup {
35    protected ActionMenuView mMenuView;
36    protected ActionMenuPresenter mActionMenuPresenter;
37    protected ActionBarContainer mSplitView;
38    protected boolean mSplitActionBar;
39    protected boolean mSplitWhenNarrow;
40    protected int mContentHeight;
41
42    protected Animator mVisibilityAnim;
43    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
44
45    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
46
47    private static final int FADE_DURATION = 200;
48
49    public AbsActionBarView(Context context) {
50        this(context, null);
51    }
52
53    public AbsActionBarView(Context context, AttributeSet attrs) {
54        this(context, attrs, 0);
55    }
56
57    public AbsActionBarView(Context context, AttributeSet attrs, int defStyleAttr) {
58        this(context, attrs, defStyleAttr, 0);
59    }
60
61    public AbsActionBarView(
62            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
63        super(context, attrs, defStyleAttr, defStyleRes);
64    }
65
66    @Override
67    protected void onConfigurationChanged(Configuration newConfig) {
68        super.onConfigurationChanged(newConfig);
69
70        // Action bar can change size on configuration changes.
71        // Reread the desired height from the theme-specified style.
72        TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
73                com.android.internal.R.attr.actionBarStyle, 0);
74        setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
75        a.recycle();
76        if (mSplitWhenNarrow) {
77            setSplitActionBar(getContext().getResources().getBoolean(
78                    com.android.internal.R.bool.split_action_bar_is_narrow));
79        }
80        if (mActionMenuPresenter != null) {
81            mActionMenuPresenter.onConfigurationChanged(newConfig);
82        }
83    }
84
85    /**
86     * Sets whether the bar should be split right now, no questions asked.
87     * @param split true if the bar should split
88     */
89    public void setSplitActionBar(boolean split) {
90        mSplitActionBar = split;
91    }
92
93    /**
94     * Sets whether the bar should split if we enter a narrow screen configuration.
95     * @param splitWhenNarrow true if the bar should check to split after a config change
96     */
97    public void setSplitWhenNarrow(boolean splitWhenNarrow) {
98        mSplitWhenNarrow = splitWhenNarrow;
99    }
100
101    public void setContentHeight(int height) {
102        mContentHeight = height;
103        requestLayout();
104    }
105
106    public int getContentHeight() {
107        return mContentHeight;
108    }
109
110    public void setSplitView(ActionBarContainer splitView) {
111        mSplitView = splitView;
112    }
113
114    /**
115     * @return Current visibility or if animating, the visibility being animated to.
116     */
117    public int getAnimatedVisibility() {
118        if (mVisibilityAnim != null) {
119            return mVisAnimListener.mFinalVisibility;
120        }
121        return getVisibility();
122    }
123
124    public void animateToVisibility(int visibility) {
125        if (mVisibilityAnim != null) {
126            mVisibilityAnim.cancel();
127        }
128        if (visibility == VISIBLE) {
129            if (getVisibility() != VISIBLE) {
130                setAlpha(0);
131                if (mSplitView != null && mMenuView != null) {
132                    mMenuView.setAlpha(0);
133                }
134            }
135            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
136            anim.setDuration(FADE_DURATION);
137            anim.setInterpolator(sAlphaInterpolator);
138            if (mSplitView != null && mMenuView != null) {
139                AnimatorSet set = new AnimatorSet();
140                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
141                splitAnim.setDuration(FADE_DURATION);
142                set.addListener(mVisAnimListener.withFinalVisibility(visibility));
143                set.play(anim).with(splitAnim);
144                set.start();
145            } else {
146                anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
147                anim.start();
148            }
149        } else {
150            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
151            anim.setDuration(FADE_DURATION);
152            anim.setInterpolator(sAlphaInterpolator);
153            if (mSplitView != null && mMenuView != null) {
154                AnimatorSet set = new AnimatorSet();
155                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
156                splitAnim.setDuration(FADE_DURATION);
157                set.addListener(mVisAnimListener.withFinalVisibility(visibility));
158                set.play(anim).with(splitAnim);
159                set.start();
160            } else {
161                anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
162                anim.start();
163            }
164        }
165    }
166
167    @Override
168    public void setVisibility(int visibility) {
169        if (visibility != getVisibility()) {
170            if (mVisibilityAnim != null) {
171                mVisibilityAnim.end();
172            }
173            super.setVisibility(visibility);
174        }
175    }
176
177    public boolean showOverflowMenu() {
178        if (mActionMenuPresenter != null) {
179            return mActionMenuPresenter.showOverflowMenu();
180        }
181        return false;
182    }
183
184    public void postShowOverflowMenu() {
185        post(new Runnable() {
186            public void run() {
187                showOverflowMenu();
188            }
189        });
190    }
191
192    public boolean hideOverflowMenu() {
193        if (mActionMenuPresenter != null) {
194            return mActionMenuPresenter.hideOverflowMenu();
195        }
196        return false;
197    }
198
199    public boolean isOverflowMenuShowing() {
200        if (mActionMenuPresenter != null) {
201            return mActionMenuPresenter.isOverflowMenuShowing();
202        }
203        return false;
204    }
205
206    public boolean isOverflowMenuShowPending() {
207        if (mActionMenuPresenter != null) {
208            return mActionMenuPresenter.isOverflowMenuShowPending();
209        }
210        return false;
211    }
212
213    public boolean isOverflowReserved() {
214        return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
215    }
216
217    public void dismissPopupMenus() {
218        if (mActionMenuPresenter != null) {
219            mActionMenuPresenter.dismissPopupMenus();
220        }
221    }
222
223    protected int measureChildView(View child, int availableWidth, int childSpecHeight,
224            int spacing) {
225        child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
226                childSpecHeight);
227
228        availableWidth -= child.getMeasuredWidth();
229        availableWidth -= spacing;
230
231        return Math.max(0, availableWidth);
232    }
233
234    static protected int next(int x, int val, boolean isRtl) {
235        return isRtl ? x - val : x + val;
236    }
237
238    protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) {
239        int childWidth = child.getMeasuredWidth();
240        int childHeight = child.getMeasuredHeight();
241        int childTop = y + (contentHeight - childHeight) / 2;
242
243        if (reverse) {
244            child.layout(x - childWidth, childTop, x, childTop + childHeight);
245        } else {
246            child.layout(x, childTop, x + childWidth, childTop + childHeight);
247        }
248
249        return  (reverse ? -childWidth : childWidth);
250    }
251
252    protected class VisibilityAnimListener implements Animator.AnimatorListener {
253        private boolean mCanceled = false;
254        int mFinalVisibility;
255
256        public VisibilityAnimListener withFinalVisibility(int visibility) {
257            mFinalVisibility = visibility;
258            return this;
259        }
260
261        @Override
262        public void onAnimationStart(Animator animation) {
263            setVisibility(VISIBLE);
264            mVisibilityAnim = animation;
265            mCanceled = false;
266        }
267
268        @Override
269        public void onAnimationEnd(Animator animation) {
270            if (mCanceled) return;
271
272            mVisibilityAnim = null;
273            setVisibility(mFinalVisibility);
274            if (mSplitView != null && mMenuView != null) {
275                mMenuView.setVisibility(mFinalVisibility);
276            }
277        }
278
279        @Override
280        public void onAnimationCancel(Animator animation) {
281            mCanceled = true;
282        }
283
284        @Override
285        public void onAnimationRepeat(Animator animation) {
286        }
287    }
288}
289