ActionBarContainer.java revision af6b97ebe0e6a67d1691c4d7789c7bc312c1e13e
1/*
2 * Copyright (C) 2010 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 */
16
17package com.android.internal.widget;
18
19import android.app.ActionBar;
20import android.content.Context;
21import android.content.res.TypedArray;
22import android.graphics.Canvas;
23import android.graphics.drawable.Drawable;
24import android.util.AttributeSet;
25import android.view.ActionMode;
26import android.view.MotionEvent;
27import android.view.View;
28import android.view.ViewGroup;
29import android.widget.FrameLayout;
30
31/**
32 * This class acts as a container for the action bar view and action mode context views.
33 * It applies special styles as needed to help handle animated transitions between them.
34 * @hide
35 */
36public class ActionBarContainer extends FrameLayout {
37    private boolean mIsTransitioning;
38    private View mTabContainer;
39    private ActionBarView mActionBarView;
40
41    private Drawable mBackground;
42    private Drawable mStackedBackground;
43    private Drawable mSplitBackground;
44    private boolean mIsSplit;
45    private boolean mIsStacked;
46
47    public ActionBarContainer(Context context) {
48        this(context, null);
49    }
50
51    public ActionBarContainer(Context context, AttributeSet attrs) {
52        super(context, attrs);
53
54        setBackgroundDrawable(null);
55
56        TypedArray a = context.obtainStyledAttributes(attrs,
57                com.android.internal.R.styleable.ActionBar);
58        mBackground = a.getDrawable(com.android.internal.R.styleable.ActionBar_background);
59        mStackedBackground = a.getDrawable(
60                com.android.internal.R.styleable.ActionBar_backgroundStacked);
61
62        if (getId() == com.android.internal.R.id.split_action_bar) {
63            mIsSplit = true;
64            mSplitBackground = a.getDrawable(
65                    com.android.internal.R.styleable.ActionBar_backgroundSplit);
66        }
67        a.recycle();
68
69        setWillNotDraw(mIsSplit ? mSplitBackground == null :
70                mBackground == null && mStackedBackground == null);
71    }
72
73    @Override
74    public void onFinishInflate() {
75        super.onFinishInflate();
76        mActionBarView = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
77    }
78
79    /**
80     * Set the action bar into a "transitioning" state. While transitioning
81     * the bar will block focus and touch from all of its descendants. This
82     * prevents the user from interacting with the bar while it is animating
83     * in or out.
84     *
85     * @param isTransitioning true if the bar is currently transitioning, false otherwise.
86     */
87    public void setTransitioning(boolean isTransitioning) {
88        mIsTransitioning = isTransitioning;
89        setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS
90                : FOCUS_AFTER_DESCENDANTS);
91    }
92
93    @Override
94    public boolean onInterceptTouchEvent(MotionEvent ev) {
95        return mIsTransitioning || super.onInterceptTouchEvent(ev);
96    }
97
98    @Override
99    public boolean onTouchEvent(MotionEvent ev) {
100        super.onTouchEvent(ev);
101
102        // An action bar always eats touch events.
103        return true;
104    }
105
106    public void setTabContainer(ScrollingTabContainerView tabView) {
107        if (mTabContainer != null) {
108            removeView(mTabContainer);
109        }
110        mTabContainer = tabView;
111        if (tabView != null) {
112            addView(tabView);
113            final ViewGroup.LayoutParams lp = tabView.getLayoutParams();
114            lp.width = LayoutParams.MATCH_PARENT;
115            lp.height = LayoutParams.WRAP_CONTENT;
116            tabView.setAllowCollapse(false);
117        }
118    }
119
120    public View getTabContainer() {
121        return mTabContainer;
122    }
123
124    @Override
125    public void onDraw(Canvas canvas) {
126        if (getWidth() == 0 || getHeight() == 0) {
127            return;
128        }
129
130        if (mIsSplit) {
131            if (mSplitBackground != null) mSplitBackground.draw(canvas);
132        } else {
133            if (mBackground != null) {
134                mBackground.draw(canvas);
135            }
136            if (mStackedBackground != null && mIsStacked) {
137                mStackedBackground.draw(canvas);
138            }
139        }
140    }
141
142    @Override
143    public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
144        // No starting an action mode for an action bar child! (Where would it go?)
145        return null;
146    }
147
148    @Override
149    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
150        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
151
152        if (mActionBarView == null) return;
153
154        final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
155        final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
156                mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
157
158        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
159            final int mode = MeasureSpec.getMode(heightMeasureSpec);
160            if (mode == MeasureSpec.AT_MOST) {
161                final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
162                setMeasuredDimension(getMeasuredWidth(),
163                        Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
164                                maxHeight));
165            }
166        }
167    }
168
169    @Override
170    public void onLayout(boolean changed, int l, int t, int r, int b) {
171        super.onLayout(changed, l, t, r, b);
172
173        final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE;
174
175        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
176            final int containerHeight = getMeasuredHeight();
177            final int tabHeight = mTabContainer.getMeasuredHeight();
178
179            if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
180                // Not showing home, put tabs on top.
181                final int count = getChildCount();
182                for (int i = 0; i < count; i++) {
183                    final View child = getChildAt(i);
184
185                    if (child == mTabContainer) continue;
186
187                    if (!mActionBarView.isCollapsed()) {
188                        child.offsetTopAndBottom(tabHeight);
189                    }
190                }
191                mTabContainer.layout(l, 0, r, tabHeight);
192            } else {
193                mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
194            }
195        }
196
197        boolean needsInvalidate = false;
198        if (mIsSplit) {
199            if (mSplitBackground != null) {
200                mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
201                needsInvalidate = true;
202            }
203        } else {
204            if (mBackground != null) {
205                mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
206                        mActionBarView.getRight(), mActionBarView.getBottom());
207                needsInvalidate = true;
208            }
209            if ((mIsStacked = hasTabs && mStackedBackground != null)) {
210                mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
211                        mTabContainer.getRight(), mTabContainer.getBottom());
212                needsInvalidate = true;
213            }
214        }
215
216        if (needsInvalidate) {
217            invalidate();
218        }
219    }
220}
221