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