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