blob: 6120a090d48bbad52803fa7a17e848b34906cab7 [file] [log] [blame]
Adam Powell45f1e082010-12-10 14:20:13 -08001/*
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
Adam Powell310849a2011-06-08 20:07:17 -070019import android.app.ActionBar;
Adam Powell45f1e082010-12-10 14:20:13 -080020import android.content.Context;
21import android.content.res.TypedArray;
Adam Powella72ef622011-07-06 22:53:11 -070022import android.graphics.Canvas;
23import android.graphics.drawable.Drawable;
Adam Powell45f1e082010-12-10 14:20:13 -080024import android.util.AttributeSet;
Adam Powell640a66e2011-04-29 10:18:53 -070025import android.view.ActionMode;
Adam Powell6ecf3d12010-12-19 13:14:58 -080026import android.view.MotionEvent;
Adam Powelldae78242011-04-25 15:23:41 -070027import android.view.View;
Adam Powellaf6b97e2011-08-11 17:40:57 -070028import android.view.ViewGroup;
Adam Powell45f1e082010-12-10 14:20:13 -080029import 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 {
Adam Powell01feaee2011-02-10 15:05:05 -080037 private boolean mIsTransitioning;
Adam Powelldae78242011-04-25 15:23:41 -070038 private View mTabContainer;
Adam Powell310849a2011-06-08 20:07:17 -070039 private ActionBarView mActionBarView;
Adam Powell01feaee2011-02-10 15:05:05 -080040
Adam Powella72ef622011-07-06 22:53:11 -070041 private Drawable mBackground;
42 private Drawable mStackedBackground;
43 private Drawable mSplitBackground;
44 private boolean mIsSplit;
45 private boolean mIsStacked;
46
Adam Powell45f1e082010-12-10 14:20:13 -080047 public ActionBarContainer(Context context) {
48 this(context, null);
49 }
50
51 public ActionBarContainer(Context context, AttributeSet attrs) {
52 super(context, attrs);
53
Adam Powella72ef622011-07-06 22:53:11 -070054 setBackgroundDrawable(null);
55
Adam Powell45f1e082010-12-10 14:20:13 -080056 TypedArray a = context.obtainStyledAttributes(attrs,
57 com.android.internal.R.styleable.ActionBar);
Adam Powella72ef622011-07-06 22:53:11 -070058 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 }
Adam Powell45f1e082010-12-10 14:20:13 -080067 a.recycle();
Adam Powella72ef622011-07-06 22:53:11 -070068
69 setWillNotDraw(mIsSplit ? mSplitBackground == null :
70 mBackground == null && mStackedBackground == null);
Adam Powell45f1e082010-12-10 14:20:13 -080071 }
Adam Powell6ecf3d12010-12-19 13:14:58 -080072
Adam Powell310849a2011-06-08 20:07:17 -070073 @Override
74 public void onFinishInflate() {
75 super.onFinishInflate();
76 mActionBarView = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
77 }
78
Adam Powellf88b9152011-09-07 14:54:32 -070079 public void setPrimaryBackground(Drawable bg) {
Adam Powella7cc06d2012-08-01 16:31:23 -070080 if (mBackground != null) {
81 mBackground.setCallback(null);
82 unscheduleDrawable(mBackground);
83 }
Adam Powellf88b9152011-09-07 14:54:32 -070084 mBackground = bg;
Adam Powella7cc06d2012-08-01 16:31:23 -070085 if (bg != null) {
86 bg.setCallback(this);
Adam Powelle8c8ae42013-02-08 17:32:24 -080087 if (mActionBarView != null) {
88 mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
89 mActionBarView.getRight(), mActionBarView.getBottom());
90 }
Adam Powella7cc06d2012-08-01 16:31:23 -070091 }
92 setWillNotDraw(mIsSplit ? mSplitBackground == null :
93 mBackground == null && mStackedBackground == null);
Adam Powellf88b9152011-09-07 14:54:32 -070094 invalidate();
95 }
96
97 public void setStackedBackground(Drawable bg) {
Adam Powella7cc06d2012-08-01 16:31:23 -070098 if (mStackedBackground != null) {
99 mStackedBackground.setCallback(null);
100 unscheduleDrawable(mStackedBackground);
101 }
Adam Powellf88b9152011-09-07 14:54:32 -0700102 mStackedBackground = bg;
Adam Powella7cc06d2012-08-01 16:31:23 -0700103 if (bg != null) {
104 bg.setCallback(this);
Adam Powelle8c8ae42013-02-08 17:32:24 -0800105 if ((mIsStacked && mStackedBackground != null)) {
106 mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
107 mTabContainer.getRight(), mTabContainer.getBottom());
108 }
Adam Powella7cc06d2012-08-01 16:31:23 -0700109 }
110 setWillNotDraw(mIsSplit ? mSplitBackground == null :
111 mBackground == null && mStackedBackground == null);
Adam Powellf88b9152011-09-07 14:54:32 -0700112 invalidate();
113 }
114
115 public void setSplitBackground(Drawable bg) {
Adam Powella7cc06d2012-08-01 16:31:23 -0700116 if (mSplitBackground != null) {
117 mSplitBackground.setCallback(null);
118 unscheduleDrawable(mSplitBackground);
119 }
Adam Powellf88b9152011-09-07 14:54:32 -0700120 mSplitBackground = bg;
Adam Powella7cc06d2012-08-01 16:31:23 -0700121 if (bg != null) {
122 bg.setCallback(this);
Adam Powelle8c8ae42013-02-08 17:32:24 -0800123 if (mIsSplit && mSplitBackground != null) {
124 mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
125 }
Adam Powella7cc06d2012-08-01 16:31:23 -0700126 }
127 setWillNotDraw(mIsSplit ? mSplitBackground == null :
128 mBackground == null && mStackedBackground == null);
Adam Powellf88b9152011-09-07 14:54:32 -0700129 invalidate();
130 }
131
Adam Powella7cc06d2012-08-01 16:31:23 -0700132 @Override
133 public void setVisibility(int visibility) {
134 super.setVisibility(visibility);
135 final boolean isVisible = visibility == VISIBLE;
136 if (mBackground != null) mBackground.setVisible(isVisible, false);
137 if (mStackedBackground != null) mStackedBackground.setVisible(isVisible, false);
138 if (mSplitBackground != null) mSplitBackground.setVisible(isVisible, false);
139 }
140
141 @Override
142 protected boolean verifyDrawable(Drawable who) {
143 return (who == mBackground && !mIsSplit) || (who == mStackedBackground && mIsStacked) ||
144 (who == mSplitBackground && mIsSplit) || super.verifyDrawable(who);
145 }
146
147 @Override
148 protected void drawableStateChanged() {
149 super.drawableStateChanged();
150 if (mBackground != null && mBackground.isStateful()) {
151 mBackground.setState(getDrawableState());
152 }
153 if (mStackedBackground != null && mStackedBackground.isStateful()) {
154 mStackedBackground.setState(getDrawableState());
155 }
156 if (mSplitBackground != null && mSplitBackground.isStateful()) {
157 mSplitBackground.setState(getDrawableState());
158 }
159 }
160
161 @Override
162 public void jumpDrawablesToCurrentState() {
163 super.jumpDrawablesToCurrentState();
164 if (mBackground != null) {
165 mBackground.jumpToCurrentState();
166 }
167 if (mStackedBackground != null) {
168 mStackedBackground.jumpToCurrentState();
169 }
170 if (mSplitBackground != null) {
171 mSplitBackground.jumpToCurrentState();
172 }
173 }
174
Fabrice Di Meglio4457e852012-09-18 19:23:12 -0700175 /**
176 * @hide
177 */
Adam Powella7cc06d2012-08-01 16:31:23 -0700178 @Override
179 public void onResolveDrawables(int layoutDirection) {
180 super.onResolveDrawables(layoutDirection);
181 if (mBackground != null) {
182 mBackground.setLayoutDirection(layoutDirection);
183 }
184 if (mStackedBackground != null) {
185 mStackedBackground.setLayoutDirection(layoutDirection);
186 }
187 if (mSplitBackground != null) {
188 mSplitBackground.setLayoutDirection(layoutDirection);
189 }
190 }
191
Adam Powell01feaee2011-02-10 15:05:05 -0800192 /**
193 * Set the action bar into a "transitioning" state. While transitioning
194 * the bar will block focus and touch from all of its descendants. This
195 * prevents the user from interacting with the bar while it is animating
196 * in or out.
197 *
198 * @param isTransitioning true if the bar is currently transitioning, false otherwise.
199 */
200 public void setTransitioning(boolean isTransitioning) {
201 mIsTransitioning = isTransitioning;
202 setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS
203 : FOCUS_AFTER_DESCENDANTS);
204 }
205
206 @Override
207 public boolean onInterceptTouchEvent(MotionEvent ev) {
208 return mIsTransitioning || super.onInterceptTouchEvent(ev);
209 }
210
Adam Powell6ecf3d12010-12-19 13:14:58 -0800211 @Override
212 public boolean onTouchEvent(MotionEvent ev) {
213 super.onTouchEvent(ev);
Adam Powelldae78242011-04-25 15:23:41 -0700214
215 // An action bar always eats touch events.
Adam Powell6ecf3d12010-12-19 13:14:58 -0800216 return true;
217 }
Adam Powelldae78242011-04-25 15:23:41 -0700218
Adam Powell7d09f042011-10-10 11:15:56 -0700219 @Override
220 public boolean onHoverEvent(MotionEvent ev) {
221 super.onHoverEvent(ev);
222
223 // An action bar always eats hover events.
224 return true;
225 }
226
Adam Powellf5645cb2011-08-10 22:49:02 -0700227 public void setTabContainer(ScrollingTabContainerView tabView) {
Adam Powelldae78242011-04-25 15:23:41 -0700228 if (mTabContainer != null) {
229 removeView(mTabContainer);
230 }
231 mTabContainer = tabView;
Adam Powell25151e42011-05-26 15:44:59 -0700232 if (tabView != null) {
233 addView(tabView);
Adam Powellaf6b97e2011-08-11 17:40:57 -0700234 final ViewGroup.LayoutParams lp = tabView.getLayoutParams();
235 lp.width = LayoutParams.MATCH_PARENT;
236 lp.height = LayoutParams.WRAP_CONTENT;
Adam Powellf5645cb2011-08-10 22:49:02 -0700237 tabView.setAllowCollapse(false);
Adam Powell25151e42011-05-26 15:44:59 -0700238 }
Adam Powelldae78242011-04-25 15:23:41 -0700239 }
240
241 public View getTabContainer() {
242 return mTabContainer;
243 }
244
245 @Override
Adam Powella72ef622011-07-06 22:53:11 -0700246 public void onDraw(Canvas canvas) {
247 if (getWidth() == 0 || getHeight() == 0) {
248 return;
249 }
250
251 if (mIsSplit) {
252 if (mSplitBackground != null) mSplitBackground.draw(canvas);
253 } else {
254 if (mBackground != null) {
255 mBackground.draw(canvas);
256 }
257 if (mStackedBackground != null && mIsStacked) {
258 mStackedBackground.draw(canvas);
259 }
260 }
261 }
262
263 @Override
Adam Powell640a66e2011-04-29 10:18:53 -0700264 public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
265 // No starting an action mode for an action bar child! (Where would it go?)
266 return null;
267 }
268
269 @Override
Adam Powelldae78242011-04-25 15:23:41 -0700270 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
271 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Adam Powelld21aa122011-05-27 13:09:52 -0700272
Adam Powellf6ce6a92011-06-29 10:25:01 -0700273 if (mActionBarView == null) return;
Adam Powell310849a2011-06-08 20:07:17 -0700274
Adam Powellf6ce6a92011-06-29 10:25:01 -0700275 final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
276 final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
277 mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
Adam Powelld21aa122011-05-27 13:09:52 -0700278
Adam Powelldae78242011-04-25 15:23:41 -0700279 if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
280 final int mode = MeasureSpec.getMode(heightMeasureSpec);
281 if (mode == MeasureSpec.AT_MOST) {
Adam Powelldae78242011-04-25 15:23:41 -0700282 final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
283 setMeasuredDimension(getMeasuredWidth(),
Adam Powellf6ce6a92011-06-29 10:25:01 -0700284 Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
285 maxHeight));
Adam Powelldae78242011-04-25 15:23:41 -0700286 }
287 }
288 }
289
290 @Override
291 public void onLayout(boolean changed, int l, int t, int r, int b) {
292 super.onLayout(changed, l, t, r, b);
Adam Powella72ef622011-07-06 22:53:11 -0700293
294 final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE;
295
Adam Powelldae78242011-04-25 15:23:41 -0700296 if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
297 final int containerHeight = getMeasuredHeight();
Adam Powell310849a2011-06-08 20:07:17 -0700298 final int tabHeight = mTabContainer.getMeasuredHeight();
299
300 if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
301 // Not showing home, put tabs on top.
302 final int count = getChildCount();
Adam Powellf6ce6a92011-06-29 10:25:01 -0700303 for (int i = 0; i < count; i++) {
Adam Powell310849a2011-06-08 20:07:17 -0700304 final View child = getChildAt(i);
305
306 if (child == mTabContainer) continue;
307
Adam Powellf6ce6a92011-06-29 10:25:01 -0700308 if (!mActionBarView.isCollapsed()) {
309 child.offsetTopAndBottom(tabHeight);
310 }
Adam Powell310849a2011-06-08 20:07:17 -0700311 }
312 mTabContainer.layout(l, 0, r, tabHeight);
313 } else {
314 mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
315 }
Adam Powelldae78242011-04-25 15:23:41 -0700316 }
Adam Powella72ef622011-07-06 22:53:11 -0700317
318 boolean needsInvalidate = false;
319 if (mIsSplit) {
320 if (mSplitBackground != null) {
321 mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
322 needsInvalidate = true;
323 }
324 } else {
325 if (mBackground != null) {
326 mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
327 mActionBarView.getRight(), mActionBarView.getBottom());
328 needsInvalidate = true;
329 }
330 if ((mIsStacked = hasTabs && mStackedBackground != null)) {
331 mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
332 mTabContainer.getRight(), mTabContainer.getBottom());
333 needsInvalidate = true;
334 }
335 }
336
337 if (needsInvalidate) {
338 invalidate();
339 }
Adam Powelldae78242011-04-25 15:23:41 -0700340 }
Adam Powell45f1e082010-12-10 14:20:13 -0800341}