ActionBarContainer.java revision 7d09f04363cdda6a3cf8b2ad1b67c9a07fa8975f
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    public void setPrimaryBackground(Drawable bg) {
80        mBackground = bg;
81        invalidate();
82    }
83
84    public void setStackedBackground(Drawable bg) {
85        mStackedBackground = bg;
86        invalidate();
87    }
88
89    public void setSplitBackground(Drawable bg) {
90        mSplitBackground = bg;
91        invalidate();
92    }
93
94    /**
95     * Set the action bar into a "transitioning" state. While transitioning
96     * the bar will block focus and touch from all of its descendants. This
97     * prevents the user from interacting with the bar while it is animating
98     * in or out.
99     *
100     * @param isTransitioning true if the bar is currently transitioning, false otherwise.
101     */
102    public void setTransitioning(boolean isTransitioning) {
103        mIsTransitioning = isTransitioning;
104        setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS
105                : FOCUS_AFTER_DESCENDANTS);
106    }
107
108    @Override
109    public boolean onInterceptTouchEvent(MotionEvent ev) {
110        return mIsTransitioning || super.onInterceptTouchEvent(ev);
111    }
112
113    @Override
114    public boolean onTouchEvent(MotionEvent ev) {
115        super.onTouchEvent(ev);
116
117        // An action bar always eats touch events.
118        return true;
119    }
120
121    @Override
122    public boolean onHoverEvent(MotionEvent ev) {
123        super.onHoverEvent(ev);
124
125        // An action bar always eats hover events.
126        return true;
127    }
128
129    public void setTabContainer(ScrollingTabContainerView tabView) {
130        if (mTabContainer != null) {
131            removeView(mTabContainer);
132        }
133        mTabContainer = tabView;
134        if (tabView != null) {
135            addView(tabView);
136            final ViewGroup.LayoutParams lp = tabView.getLayoutParams();
137            lp.width = LayoutParams.MATCH_PARENT;
138            lp.height = LayoutParams.WRAP_CONTENT;
139            tabView.setAllowCollapse(false);
140        }
141    }
142
143    public View getTabContainer() {
144        return mTabContainer;
145    }
146
147    @Override
148    public void onDraw(Canvas canvas) {
149        if (getWidth() == 0 || getHeight() == 0) {
150            return;
151        }
152
153        if (mIsSplit) {
154            if (mSplitBackground != null) mSplitBackground.draw(canvas);
155        } else {
156            if (mBackground != null) {
157                mBackground.draw(canvas);
158            }
159            if (mStackedBackground != null && mIsStacked) {
160                mStackedBackground.draw(canvas);
161            }
162        }
163    }
164
165    @Override
166    public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
167        // No starting an action mode for an action bar child! (Where would it go?)
168        return null;
169    }
170
171    @Override
172    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
173        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
174
175        if (mActionBarView == null) return;
176
177        final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
178        final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
179                mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
180
181        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
182            final int mode = MeasureSpec.getMode(heightMeasureSpec);
183            if (mode == MeasureSpec.AT_MOST) {
184                final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
185                setMeasuredDimension(getMeasuredWidth(),
186                        Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
187                                maxHeight));
188            }
189        }
190    }
191
192    @Override
193    public void onLayout(boolean changed, int l, int t, int r, int b) {
194        super.onLayout(changed, l, t, r, b);
195
196        final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE;
197
198        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
199            final int containerHeight = getMeasuredHeight();
200            final int tabHeight = mTabContainer.getMeasuredHeight();
201
202            if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
203                // Not showing home, put tabs on top.
204                final int count = getChildCount();
205                for (int i = 0; i < count; i++) {
206                    final View child = getChildAt(i);
207
208                    if (child == mTabContainer) continue;
209
210                    if (!mActionBarView.isCollapsed()) {
211                        child.offsetTopAndBottom(tabHeight);
212                    }
213                }
214                mTabContainer.layout(l, 0, r, tabHeight);
215            } else {
216                mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
217            }
218        }
219
220        boolean needsInvalidate = false;
221        if (mIsSplit) {
222            if (mSplitBackground != null) {
223                mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
224                needsInvalidate = true;
225            }
226        } else {
227            if (mBackground != null) {
228                mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
229                        mActionBarView.getRight(), mActionBarView.getBottom());
230                needsInvalidate = true;
231            }
232            if ((mIsStacked = hasTabs && mStackedBackground != null)) {
233                mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
234                        mTabContainer.getRight(), mTabContainer.getBottom());
235                needsInvalidate = true;
236            }
237        }
238
239        if (needsInvalidate) {
240            invalidate();
241        }
242    }
243}
244