blob: 81d02eec7196cf11dc7b363bb23f50ef74d637d1 [file] [log] [blame]
Adam Powell33b97432010-04-20 10:01:14 -07001/*
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
Adam Powell89e06452010-06-23 20:24:52 -070017package com.android.internal.widget;
Adam Powell33b97432010-04-20 10:01:14 -070018
Adam Powell96675b12010-06-10 18:58:59 -070019import com.android.internal.R;
Adam Powell96675b12010-06-10 18:58:59 -070020import com.android.internal.view.menu.ActionMenuItem;
Adam Powell7ade1be2010-06-17 12:51:21 -070021import com.android.internal.view.menu.ActionMenuView;
Adam Powell96675b12010-06-10 18:58:59 -070022import com.android.internal.view.menu.MenuBuilder;
Adam Powell33b97432010-04-20 10:01:14 -070023
24import android.app.ActionBar;
Adam Powell8515ee82010-11-30 14:09:55 -080025import android.app.ActionBar.OnNavigationListener;
Adam Powell9146ac72010-08-16 18:53:38 -070026import android.app.Activity;
Adam Powell33b97432010-04-20 10:01:14 -070027import android.content.Context;
28import android.content.pm.ApplicationInfo;
29import android.content.pm.PackageManager;
Adam Powell9ab97872010-10-26 21:47:29 -070030import android.content.pm.PackageManager.NameNotFoundException;
Adam Powell33b97432010-04-20 10:01:14 -070031import android.content.res.TypedArray;
Adam Powell33b97432010-04-20 10:01:14 -070032import android.graphics.drawable.Drawable;
Adam Powell2a7ea672011-01-23 20:25:15 -080033import android.text.TextUtils;
Adam Powell661c9082010-07-02 10:09:44 -070034import android.text.TextUtils.TruncateAt;
Adam Powell33b97432010-04-20 10:01:14 -070035import android.util.AttributeSet;
Adam Powell9ab97872010-10-26 21:47:29 -070036import android.util.Log;
Adam Powell9146ac72010-08-16 18:53:38 -070037import android.view.ActionMode;
Adam Powell661c9082010-07-02 10:09:44 -070038import android.view.Gravity;
Adam Powell89e06452010-06-23 20:24:52 -070039import android.view.LayoutInflater;
40import android.view.Menu;
41import android.view.View;
42import android.view.ViewGroup;
Adam Powell9ab97872010-10-26 21:47:29 -070043import android.view.ViewParent;
Adam Powell8d12e202010-11-15 16:44:17 -080044import android.view.Window;
Adam Powella4082912010-06-04 18:34:02 -070045import android.widget.AdapterView;
Adam Powell2b0952b2011-03-09 00:15:38 -080046import android.widget.FrameLayout;
Adam Powell2b6230e2010-09-07 17:55:25 -070047import android.widget.HorizontalScrollView;
Adam Powell33b97432010-04-20 10:01:14 -070048import android.widget.ImageView;
Adam Powell0e94b512010-06-29 17:58:20 -070049import android.widget.LinearLayout;
Adam Powell6af97e12010-11-11 21:11:53 -080050import android.widget.ProgressBar;
Adam Powella4082912010-06-04 18:34:02 -070051import android.widget.Spinner;
52import android.widget.SpinnerAdapter;
Adam Powell33b97432010-04-20 10:01:14 -070053import android.widget.TextView;
54
Adam Powell33b97432010-04-20 10:01:14 -070055/**
56 * @hide
57 */
58public class ActionBarView extends ViewGroup {
59 private static final String TAG = "ActionBarView";
Adam Powellbe4d68e2010-10-08 18:16:34 -070060
Adam Powell33b97432010-04-20 10:01:14 -070061 /**
62 * Display options applied by default
63 */
64 public static final int DISPLAY_DEFAULT = 0;
65
66 /**
67 * Display options that require re-layout as opposed to a simple invalidate
68 */
Adam Powella1700782010-05-13 13:27:35 -070069 private static final int DISPLAY_RELAYOUT_MASK =
Adam Powell9ab97872010-10-26 21:47:29 -070070 ActionBar.DISPLAY_SHOW_HOME |
71 ActionBar.DISPLAY_USE_LOGO |
72 ActionBar.DISPLAY_HOME_AS_UP |
73 ActionBar.DISPLAY_SHOW_CUSTOM |
74 ActionBar.DISPLAY_SHOW_TITLE;
75
76 private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
Adam Powell33b97432010-04-20 10:01:14 -070077
78 private final int mContentHeight;
79
80 private int mNavigationMode;
Adam Powell9ab97872010-10-26 21:47:29 -070081 private int mDisplayOptions = ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP;
Adam Powell33b97432010-04-20 10:01:14 -070082 private CharSequence mTitle;
83 private CharSequence mSubtitle;
84 private Drawable mIcon;
85 private Drawable mLogo;
Adam Powellbe4d68e2010-10-08 18:16:34 -070086 private Drawable mDivider;
Adam Powell33b97432010-04-20 10:01:14 -070087
Ed Heyl1c603002010-11-18 12:18:23 -080088 private View mHomeLayout;
89 private View mHomeAsUpView;
Adam Powell33b97432010-04-20 10:01:14 -070090 private ImageView mIconView;
Adam Powell0e94b512010-06-29 17:58:20 -070091 private LinearLayout mTitleLayout;
Adam Powell33b97432010-04-20 10:01:14 -070092 private TextView mTitleView;
93 private TextView mSubtitleView;
Adam Powella4082912010-06-04 18:34:02 -070094 private Spinner mSpinner;
Adam Powell3f7f7ac2010-12-05 16:44:38 -080095 private LinearLayout mListNavLayout;
Adam Powell2b6230e2010-09-07 17:55:25 -070096 private HorizontalScrollView mTabScrollView;
Adam Powell661c9082010-07-02 10:09:44 -070097 private LinearLayout mTabLayout;
Adam Powella4082912010-06-04 18:34:02 -070098 private View mCustomNavView;
Adam Powell6af97e12010-11-11 21:11:53 -080099 private ProgressBar mProgressView;
100 private ProgressBar mIndeterminateProgressView;
101
102 private int mProgressBarPadding;
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800103 private int mItemPadding;
Adam Powell33b97432010-04-20 10:01:14 -0700104
Adam Powelle2194442010-08-12 18:13:03 -0700105 private int mTitleStyleRes;
106 private int mSubtitleStyleRes;
Adam Powell6af97e12010-11-11 21:11:53 -0800107 private int mProgressStyle;
108 private int mIndeterminateProgressStyle;
Adam Powelle2194442010-08-12 18:13:03 -0700109
Adam Powell33b97432010-04-20 10:01:14 -0700110 private boolean mShowMenu;
Adam Powelle92ea342010-07-14 14:45:50 -0700111 private boolean mUserTitle;
Adam Powell33b97432010-04-20 10:01:14 -0700112
Adam Powell96675b12010-06-10 18:58:59 -0700113 private MenuBuilder mOptionsMenu;
Adam Powell7ade1be2010-06-17 12:51:21 -0700114 private ActionMenuView mMenuView;
Adam Powell96675b12010-06-10 18:58:59 -0700115
Adam Powelle2194442010-08-12 18:13:03 -0700116 private ActionBarContextView mContextView;
117
Adam Powell33b97432010-04-20 10:01:14 -0700118 private ActionMenuItem mLogoNavItem;
Adam Powell9ab97872010-10-26 21:47:29 -0700119
120 private SpinnerAdapter mSpinnerAdapter;
Adam Powell8515ee82010-11-30 14:09:55 -0800121 private OnNavigationListener mCallback;
Adam Powell33b97432010-04-20 10:01:14 -0700122
Adam Powella4082912010-06-04 18:34:02 -0700123 private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
124 new AdapterView.OnItemSelectedListener() {
125 public void onItemSelected(AdapterView parent, View view, int position, long id) {
126 if (mCallback != null) {
127 mCallback.onNavigationItemSelected(position, id);
128 }
129 }
130 public void onNothingSelected(AdapterView parent) {
131 // Do nothing
132 }
133 };
134
Adam Powell2b6230e2010-09-07 17:55:25 -0700135 private OnClickListener mTabClickListener = null;
136
Adam Powell33b97432010-04-20 10:01:14 -0700137 public ActionBarView(Context context, AttributeSet attrs) {
138 super(context, attrs);
139
Adam Powell654e4e42011-01-03 16:33:50 -0800140 // Background is always provided by the container.
141 setBackgroundResource(0);
142
Adam Powell33b97432010-04-20 10:01:14 -0700143 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
144
Adam Powell9ab97872010-10-26 21:47:29 -0700145 ApplicationInfo appInfo = context.getApplicationInfo();
Adam Powell33b97432010-04-20 10:01:14 -0700146 PackageManager pm = context.getPackageManager();
Adam Powell661c9082010-07-02 10:09:44 -0700147 mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode,
148 ActionBar.NAVIGATION_MODE_STANDARD);
Adam Powell33b97432010-04-20 10:01:14 -0700149 mTitle = a.getText(R.styleable.ActionBar_title);
150 mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
Adam Powell33b97432010-04-20 10:01:14 -0700151
152 mLogo = a.getDrawable(R.styleable.ActionBar_logo);
153 if (mLogo == null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700154 if (context instanceof Activity) {
155 try {
156 mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
157 } catch (NameNotFoundException e) {
158 Log.e(TAG, "Activity component name not found!", e);
159 }
160 }
161 if (mLogo == null) {
162 mLogo = appInfo.loadLogo(pm);
163 }
Adam Powell33b97432010-04-20 10:01:14 -0700164 }
Adam Powell9ab97872010-10-26 21:47:29 -0700165
Adam Powell33b97432010-04-20 10:01:14 -0700166 mIcon = a.getDrawable(R.styleable.ActionBar_icon);
167 if (mIcon == null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700168 if (context instanceof Activity) {
169 try {
170 mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
171 } catch (NameNotFoundException e) {
172 Log.e(TAG, "Activity component name not found!", e);
173 }
174 }
175 if (mIcon == null) {
176 mIcon = appInfo.loadIcon(pm);
177 }
Adam Powell33b97432010-04-20 10:01:14 -0700178 }
Adam Powell9ab97872010-10-26 21:47:29 -0700179
Ed Heyl1c603002010-11-18 12:18:23 -0800180 final LayoutInflater inflater = LayoutInflater.from(context);
Adam Powell9ab97872010-10-26 21:47:29 -0700181
Ed Heyl1c603002010-11-18 12:18:23 -0800182 final int homeResId = a.getResourceId(
Adam Powellb33be1c2010-11-18 12:11:40 -0800183 com.android.internal.R.styleable.ActionBar_homeLayout,
184 com.android.internal.R.layout.action_bar_home);
Adam Powell9ab97872010-10-26 21:47:29 -0700185
Ed Heyl1c603002010-11-18 12:18:23 -0800186 mHomeLayout = inflater.inflate(homeResId, this, false);
187
188 mHomeAsUpView = mHomeLayout.findViewById(com.android.internal.R.id.up);
189 mIconView = (ImageView) mHomeLayout.findViewById(com.android.internal.R.id.home);
Adam Powell33b97432010-04-20 10:01:14 -0700190
Adam Powelle2194442010-08-12 18:13:03 -0700191 mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
192 mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
Adam Powell6af97e12010-11-11 21:11:53 -0800193 mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
194 mIndeterminateProgressStyle = a.getResourceId(
195 R.styleable.ActionBar_indeterminateProgressStyle, 0);
196
197 mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800198 mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
Adam Powelle2194442010-08-12 18:13:03 -0700199
Adam Powell9ab97872010-10-26 21:47:29 -0700200 setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
201
Adam Powell33b97432010-04-20 10:01:14 -0700202 final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
203 if (customNavId != 0) {
Ed Heyl1c603002010-11-18 12:18:23 -0800204 mCustomNavView = (View) inflater.inflate(customNavId, this, false);
Adam Powell9ab97872010-10-26 21:47:29 -0700205 mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
206 setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
Adam Powell33b97432010-04-20 10:01:14 -0700207 }
208
Adam Powelle2194442010-08-12 18:13:03 -0700209 mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
Adam Powellbe4d68e2010-10-08 18:16:34 -0700210
211 mDivider = a.getDrawable(R.styleable.ActionBar_divider);
Adam Powell6b336f82010-08-10 20:13:01 -0700212
Adam Powell33b97432010-04-20 10:01:14 -0700213 a.recycle();
Adam Powell33b97432010-04-20 10:01:14 -0700214
Ben Komaload199ec2010-11-01 12:24:16 -0700215 mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
216 mHomeLayout.setOnClickListener(new OnClickListener() {
Adam Powellb33be1c2010-11-18 12:11:40 -0800217 public void onClick(View v) {
218 Context context = getContext();
219 if (context instanceof Activity) {
220 Activity activity = (Activity) context;
221 activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
222 }
Ben Komaload199ec2010-11-01 12:24:16 -0700223 }
Ben Komaload199ec2010-11-01 12:24:16 -0700224 });
225 mHomeLayout.setClickable(true);
226 mHomeLayout.setFocusable(true);
Adam Powell33b97432010-04-20 10:01:14 -0700227 }
Adam Powella7db0372010-06-30 17:08:47 -0700228
Adam Powell6af97e12010-11-11 21:11:53 -0800229 public void initProgress() {
230 mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle);
231 mProgressView.setId(R.id.progress_horizontal);
232 mProgressView.setMax(10000);
233 addView(mProgressView);
234 }
235
236 public void initIndeterminateProgress() {
237 mIndeterminateProgressView = new ProgressBar(mContext, null, 0,
238 mIndeterminateProgressStyle);
239 mIndeterminateProgressView.setId(R.id.progress_circular);
240 addView(mIndeterminateProgressView);
241 }
242
Adam Powell9146ac72010-08-16 18:53:38 -0700243 @Override
244 public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
245 // No starting an action mode for an action bar child! (Where would it go?)
246 return null;
247 }
248
Adam Powell8515ee82010-11-30 14:09:55 -0800249 public void setCallback(OnNavigationListener callback) {
Adam Powell96675b12010-06-10 18:58:59 -0700250 mCallback = callback;
Adam Powell33b97432010-04-20 10:01:14 -0700251 }
Adam Powella7db0372010-06-30 17:08:47 -0700252
Adam Powell96675b12010-06-10 18:58:59 -0700253 public void setMenu(Menu menu) {
Adam Powellf2d7a5d2011-02-07 18:05:24 -0800254 if (menu == mOptionsMenu) return;
255
Adam Powell96675b12010-06-10 18:58:59 -0700256 MenuBuilder builder = (MenuBuilder) menu;
257 mOptionsMenu = builder;
258 if (mMenuView != null) {
259 removeView(mMenuView);
Adam Powell33b97432010-04-20 10:01:14 -0700260 }
Adam Powell7ade1be2010-06-17 12:51:21 -0700261 final ActionMenuView menuView = (ActionMenuView) builder.getMenuView(
262 MenuBuilder.TYPE_ACTION_BUTTON, null);
Adam Powell96675b12010-06-10 18:58:59 -0700263 final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
264 LayoutParams.MATCH_PARENT);
265 menuView.setLayoutParams(layoutParams);
266 addView(menuView);
267 mMenuView = menuView;
Adam Powell33b97432010-04-20 10:01:14 -0700268 }
Adam Powella7db0372010-06-30 17:08:47 -0700269
Adam Powell8028dd32010-07-15 10:16:33 -0700270 public boolean showOverflowMenu() {
271 if (mMenuView != null) {
272 return mMenuView.showOverflowMenu();
273 }
274 return false;
275 }
276
Adam Powell8515ee82010-11-30 14:09:55 -0800277 public void openOverflowMenu() {
278 if (mMenuView != null) {
279 mMenuView.openOverflowMenu();
280 }
281 }
282
Adam Powell6c6f5752010-08-20 18:34:46 -0700283 public void postShowOverflowMenu() {
284 post(new Runnable() {
285 public void run() {
286 showOverflowMenu();
287 }
288 });
289 }
290
Adam Powellf75eeb22010-08-10 15:59:40 -0700291 public boolean hideOverflowMenu() {
292 if (mMenuView != null) {
293 return mMenuView.hideOverflowMenu();
294 }
295 return false;
296 }
297
Adam Powellf6148c52010-08-11 21:10:16 -0700298 public boolean isOverflowMenuShowing() {
299 if (mMenuView != null) {
300 return mMenuView.isOverflowMenuShowing();
301 }
302 return false;
303 }
304
Adam Powell8515ee82010-11-30 14:09:55 -0800305 public boolean isOverflowMenuOpen() {
306 if (mMenuView != null) {
307 return mMenuView.isOverflowMenuOpen();
308 }
309 return false;
310 }
311
Adam Powell8028dd32010-07-15 10:16:33 -0700312 public boolean isOverflowReserved() {
313 return mMenuView != null && mMenuView.isOverflowReserved();
314 }
315
Adam Powell33b97432010-04-20 10:01:14 -0700316 public void setCustomNavigationView(View view) {
Adam Powell9ab97872010-10-26 21:47:29 -0700317 final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
318 if (mCustomNavView != null && showCustom) {
319 removeView(mCustomNavView);
320 }
Adam Powella4082912010-06-04 18:34:02 -0700321 mCustomNavView = view;
Adam Powell9ab97872010-10-26 21:47:29 -0700322 if (mCustomNavView != null && showCustom) {
323 addView(mCustomNavView);
Adam Powell33b97432010-04-20 10:01:14 -0700324 }
Adam Powell33b97432010-04-20 10:01:14 -0700325 }
Adam Powella7db0372010-06-30 17:08:47 -0700326
Adam Powell33b97432010-04-20 10:01:14 -0700327 public CharSequence getTitle() {
328 return mTitle;
329 }
Adam Powella7db0372010-06-30 17:08:47 -0700330
Adam Powelle92ea342010-07-14 14:45:50 -0700331 /**
332 * Set the action bar title. This will always replace or override window titles.
333 * @param title Title to set
334 *
335 * @see #setWindowTitle(CharSequence)
336 */
Adam Powell33b97432010-04-20 10:01:14 -0700337 public void setTitle(CharSequence title) {
Adam Powelle92ea342010-07-14 14:45:50 -0700338 mUserTitle = true;
339 setTitleImpl(title);
340 }
341
342 /**
343 * Set the window title. A window title will always be replaced or overridden by a user title.
344 * @param title Title to set
345 *
346 * @see #setTitle(CharSequence)
347 */
348 public void setWindowTitle(CharSequence title) {
349 if (!mUserTitle) {
350 setTitleImpl(title);
351 }
352 }
353
354 private void setTitleImpl(CharSequence title) {
Adam Powell33b97432010-04-20 10:01:14 -0700355 mTitle = title;
356 if (mTitleView != null) {
357 mTitleView.setText(title);
Adam Powell2a7ea672011-01-23 20:25:15 -0800358 mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ?
359 GONE : VISIBLE);
Adam Powell33b97432010-04-20 10:01:14 -0700360 }
361 if (mLogoNavItem != null) {
362 mLogoNavItem.setTitle(title);
363 }
364 }
Adam Powella7db0372010-06-30 17:08:47 -0700365
Adam Powell33b97432010-04-20 10:01:14 -0700366 public CharSequence getSubtitle() {
367 return mSubtitle;
368 }
Adam Powella7db0372010-06-30 17:08:47 -0700369
Adam Powell33b97432010-04-20 10:01:14 -0700370 public void setSubtitle(CharSequence subtitle) {
371 mSubtitle = subtitle;
372 if (mSubtitleView != null) {
373 mSubtitleView.setText(subtitle);
Adam Powell04587962010-11-11 22:15:07 -0800374 mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
Adam Powell2a7ea672011-01-23 20:25:15 -0800375 mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ?
376 GONE : VISIBLE);
Adam Powell33b97432010-04-20 10:01:14 -0700377 }
378 }
Adam Powella7db0372010-06-30 17:08:47 -0700379
Adam Powell33b97432010-04-20 10:01:14 -0700380 public void setDisplayOptions(int options) {
Adam Powella1700782010-05-13 13:27:35 -0700381 final int flagsChanged = options ^ mDisplayOptions;
Adam Powell33b97432010-04-20 10:01:14 -0700382 mDisplayOptions = options;
383 if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
Adam Powell9ab97872010-10-26 21:47:29 -0700384 final int vis = (options & ActionBar.DISPLAY_SHOW_HOME) != 0 ? VISIBLE : GONE;
385 mHomeLayout.setVisibility(vis);
386
387 if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
388 mHomeAsUpView.setVisibility((options & ActionBar.DISPLAY_HOME_AS_UP) != 0
Adam Powell8fca37c2011-03-04 15:33:18 -0800389 ? VISIBLE : GONE);
Adam Powella1700782010-05-13 13:27:35 -0700390 }
Adam Powell9ab97872010-10-26 21:47:29 -0700391
Ed Heyl1c603002010-11-18 12:18:23 -0800392 if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
393 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
394 mIconView.setImageDrawable(logoVis ? mLogo : mIcon);
Adam Powell9ab97872010-10-26 21:47:29 -0700395 }
396
397 if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
398 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
399 initTitle();
400 } else {
401 removeView(mTitleLayout);
402 }
403 }
404
405 if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
406 if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
407 addView(mCustomNavView);
408 } else {
409 removeView(mCustomNavView);
410 }
Adam Powella1700782010-05-13 13:27:35 -0700411 }
412
Adam Powell33b97432010-04-20 10:01:14 -0700413 requestLayout();
414 } else {
415 invalidate();
416 }
417 }
418
419 public void setNavigationMode(int mode) {
Adam Powella1700782010-05-13 13:27:35 -0700420 final int oldMode = mNavigationMode;
421 if (mode != oldMode) {
422 switch (oldMode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700423 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powella4082912010-06-04 18:34:02 -0700424 if (mSpinner != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800425 removeView(mListNavLayout);
Adam Powella4082912010-06-04 18:34:02 -0700426 }
427 break;
Adam Powell661c9082010-07-02 10:09:44 -0700428 case ActionBar.NAVIGATION_MODE_TABS:
429 if (mTabLayout != null) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700430 removeView(mTabScrollView);
Adam Powell661c9082010-07-02 10:09:44 -0700431 }
Adam Powella1700782010-05-13 13:27:35 -0700432 }
433
434 switch (mode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700435 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800436 if (mSpinner == null) {
437 mSpinner = new Spinner(mContext, null,
438 com.android.internal.R.attr.actionDropDownStyle);
439 mListNavLayout = new LinearLayout(mContext, null,
440 com.android.internal.R.attr.actionBarTabBarStyle);
441 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
Adam Powelle7d46842011-01-13 21:36:09 -0800442 LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800443 params.gravity = Gravity.CENTER;
444 mListNavLayout.addView(mSpinner, params);
445 }
446 if (mSpinner.getAdapter() != mSpinnerAdapter) {
447 mSpinner.setAdapter(mSpinnerAdapter);
448 }
Adam Powella4082912010-06-04 18:34:02 -0700449 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800450 addView(mListNavLayout);
Adam Powella4082912010-06-04 18:34:02 -0700451 break;
Adam Powell661c9082010-07-02 10:09:44 -0700452 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powell9ab97872010-10-26 21:47:29 -0700453 ensureTabsExist();
Adam Powell2b6230e2010-09-07 17:55:25 -0700454 addView(mTabScrollView);
Adam Powell661c9082010-07-02 10:09:44 -0700455 break;
Adam Powella1700782010-05-13 13:27:35 -0700456 }
Adam Powell33b97432010-04-20 10:01:14 -0700457 mNavigationMode = mode;
458 requestLayout();
459 }
460 }
461
Adam Powell9ab97872010-10-26 21:47:29 -0700462 private void ensureTabsExist() {
463 if (mTabScrollView == null) {
464 mTabScrollView = new HorizontalScrollView(getContext());
Adam Powellc18c38f2011-03-15 11:57:46 -0700465 mTabScrollView.setHorizontalFadingEdgeEnabled(true);
Adam Powell9ab97872010-10-26 21:47:29 -0700466 mTabLayout = new LinearLayout(getContext(), null,
467 com.android.internal.R.attr.actionBarTabBarStyle);
468 mTabScrollView.addView(mTabLayout);
469 }
470 }
471
Adam Powella4082912010-06-04 18:34:02 -0700472 public void setDropdownAdapter(SpinnerAdapter adapter) {
Adam Powell9ab97872010-10-26 21:47:29 -0700473 mSpinnerAdapter = adapter;
474 if (mSpinner != null) {
475 mSpinner.setAdapter(adapter);
476 }
477 }
478
479 public SpinnerAdapter getDropdownAdapter() {
480 return mSpinnerAdapter;
Adam Powella4082912010-06-04 18:34:02 -0700481 }
Adam Powell17809772010-07-21 13:25:11 -0700482
483 public void setDropdownSelectedPosition(int position) {
484 mSpinner.setSelection(position);
485 }
486
487 public int getDropdownSelectedPosition() {
488 return mSpinner.getSelectedItemPosition();
489 }
490
Adam Powell33b97432010-04-20 10:01:14 -0700491 public View getCustomNavigationView() {
Adam Powella4082912010-06-04 18:34:02 -0700492 return mCustomNavView;
Adam Powell33b97432010-04-20 10:01:14 -0700493 }
494
495 public int getNavigationMode() {
496 return mNavigationMode;
497 }
498
499 public int getDisplayOptions() {
500 return mDisplayOptions;
501 }
Adam Powella7db0372010-06-30 17:08:47 -0700502
Adam Powell661c9082010-07-02 10:09:44 -0700503 private TabView createTabView(ActionBar.Tab tab) {
504 final TabView tabView = new TabView(getContext(), tab);
505 tabView.setFocusable(true);
Adam Powell2b6230e2010-09-07 17:55:25 -0700506
507 if (mTabClickListener == null) {
508 mTabClickListener = new TabClickListener();
509 }
510 tabView.setOnClickListener(mTabClickListener);
Adam Powell661c9082010-07-02 10:09:44 -0700511 return tabView;
512 }
513
Adam Powell81b89442010-11-02 17:58:56 -0700514 public void addTab(ActionBar.Tab tab, boolean setSelected) {
Adam Powell9ab97872010-10-26 21:47:29 -0700515 ensureTabsExist();
Adam Powell2b6230e2010-09-07 17:55:25 -0700516 View tabView = createTabView(tab);
Adam Powell661c9082010-07-02 10:09:44 -0700517 mTabLayout.addView(tabView);
Adam Powell81b89442010-11-02 17:58:56 -0700518 if (setSelected) {
Adam Powell661c9082010-07-02 10:09:44 -0700519 tabView.setSelected(true);
520 }
521 }
522
Adam Powell81b89442010-11-02 17:58:56 -0700523 public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
Adam Powell9ab97872010-10-26 21:47:29 -0700524 ensureTabsExist();
Adam Powell661c9082010-07-02 10:09:44 -0700525 final TabView tabView = createTabView(tab);
526 mTabLayout.addView(tabView, position);
Adam Powell81b89442010-11-02 17:58:56 -0700527 if (setSelected) {
Adam Powell661c9082010-07-02 10:09:44 -0700528 tabView.setSelected(true);
529 }
530 }
531
532 public void removeTabAt(int position) {
Adam Powell9ab97872010-10-26 21:47:29 -0700533 if (mTabLayout != null) {
534 mTabLayout.removeViewAt(position);
535 }
Adam Powell661c9082010-07-02 10:09:44 -0700536 }
537
Adam Powell0c24a552010-11-03 16:44:11 -0700538 public void removeAllTabs() {
539 if (mTabLayout != null) {
540 mTabLayout.removeAllViews();
541 }
542 }
543
Adam Powella7db0372010-06-30 17:08:47 -0700544 @Override
545 protected LayoutParams generateDefaultLayoutParams() {
546 // Used by custom nav views if they don't supply layout params. Everything else
547 // added to an ActionBarView should have them already.
Adam Powell9ab97872010-10-26 21:47:29 -0700548 return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
Adam Powella7db0372010-06-30 17:08:47 -0700549 }
550
Adam Powell33b97432010-04-20 10:01:14 -0700551 @Override
552 protected void onFinishInflate() {
553 super.onFinishInflate();
554
Adam Powell9ab97872010-10-26 21:47:29 -0700555 addView(mHomeLayout);
556
Adam Powell9ab97872010-10-26 21:47:29 -0700557 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
558 final ViewParent parent = mCustomNavView.getParent();
559 if (parent != this) {
560 if (parent instanceof ViewGroup) {
561 ((ViewGroup) parent).removeView(mCustomNavView);
562 }
Adam Powella4082912010-06-04 18:34:02 -0700563 addView(mCustomNavView);
Adam Powell33b97432010-04-20 10:01:14 -0700564 }
Adam Powell33b97432010-04-20 10:01:14 -0700565 }
566 }
Adam Powella1700782010-05-13 13:27:35 -0700567
568 private void initTitle() {
569 LayoutInflater inflater = LayoutInflater.from(getContext());
Adam Powell0e94b512010-06-29 17:58:20 -0700570 mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
571 mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
572 mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
Adam Powelle2194442010-08-12 18:13:03 -0700573
574 if (mTitleStyleRes != 0) {
575 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
576 }
Adam Powella1700782010-05-13 13:27:35 -0700577 if (mTitle != null) {
578 mTitleView.setText(mTitle);
579 }
Adam Powelle2194442010-08-12 18:13:03 -0700580
581 if (mSubtitleStyleRes != 0) {
582 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
583 }
Adam Powell0e94b512010-06-29 17:58:20 -0700584 if (mSubtitle != null) {
585 mSubtitleView.setText(mSubtitle);
586 mSubtitleView.setVisibility(VISIBLE);
587 }
Adam Powelle2194442010-08-12 18:13:03 -0700588
Adam Powell0e94b512010-06-29 17:58:20 -0700589 addView(mTitleLayout);
Adam Powella1700782010-05-13 13:27:35 -0700590 }
Adam Powell33b97432010-04-20 10:01:14 -0700591
Adam Powell661c9082010-07-02 10:09:44 -0700592 public void setTabSelected(int position) {
Adam Powell9ab97872010-10-26 21:47:29 -0700593 ensureTabsExist();
Adam Powell661c9082010-07-02 10:09:44 -0700594 final int tabCount = mTabLayout.getChildCount();
595 for (int i = 0; i < tabCount; i++) {
596 final View child = mTabLayout.getChildAt(i);
597 child.setSelected(i == position);
598 }
599 }
600
Adam Powelle2194442010-08-12 18:13:03 -0700601 public void setContextView(ActionBarContextView view) {
602 mContextView = view;
603 }
604
Adam Powell33b97432010-04-20 10:01:14 -0700605 @Override
606 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
607 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
608 if (widthMode != MeasureSpec.EXACTLY) {
609 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
610 "with android:layout_width=\"match_parent\" (or fill_parent)");
611 }
612
613 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
614 if (heightMode != MeasureSpec.AT_MOST) {
615 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
616 "with android:layout_height=\"wrap_content\"");
617 }
618
619 int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
Adam Powelle2194442010-08-12 18:13:03 -0700620
621 int maxHeight = mContentHeight > 0 ?
622 mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
Adam Powell33b97432010-04-20 10:01:14 -0700623
Adam Powelle2194442010-08-12 18:13:03 -0700624 final int verticalPadding = getPaddingTop() + getPaddingBottom();
Adam Powell9ab97872010-10-26 21:47:29 -0700625 final int paddingLeft = getPaddingLeft();
626 final int paddingRight = getPaddingRight();
Adam Powelle2194442010-08-12 18:13:03 -0700627 final int height = maxHeight - verticalPadding;
Adam Powella1700782010-05-13 13:27:35 -0700628 final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
Adam Powell33b97432010-04-20 10:01:14 -0700629
Adam Powell9ab97872010-10-26 21:47:29 -0700630 int availableWidth = contentWidth - paddingLeft - paddingRight;
631 int leftOfCenter = availableWidth / 2;
632 int rightOfCenter = leftOfCenter;
633
634 if (mHomeLayout.getVisibility() != GONE) {
Ed Heyl1c603002010-11-18 12:18:23 -0800635 mHomeLayout.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
636 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
637 final int homeWidth = mHomeLayout.getMeasuredWidth();
638 availableWidth -= homeWidth;
639 leftOfCenter -= homeWidth;
Adam Powell33b97432010-04-20 10:01:14 -0700640 }
Adam Powell96675b12010-06-10 18:58:59 -0700641
642 if (mMenuView != null) {
643 availableWidth = measureChildView(mMenuView, availableWidth,
Adam Powell7ade1be2010-06-17 12:51:21 -0700644 childSpecHeight, 0);
Adam Powell9ab97872010-10-26 21:47:29 -0700645 rightOfCenter -= mMenuView.getMeasuredWidth();
Adam Powell33b97432010-04-20 10:01:14 -0700646 }
Adam Powell9ab97872010-10-26 21:47:29 -0700647
Adam Powell2a7ea672011-01-23 20:25:15 -0800648 boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800649 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
650 if (showTitle) {
Adam Powell9ab97872010-10-26 21:47:29 -0700651 availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
652 leftOfCenter -= mTitleLayout.getMeasuredWidth();
653 }
654
Adam Powell33b97432010-04-20 10:01:14 -0700655 switch (mNavigationMode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700656 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800657 if (mListNavLayout != null) {
658 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
659 availableWidth -= itemPaddingSize;
660 leftOfCenter -= itemPaddingSize;
661 mListNavLayout.measure(
Adam Powella7db0372010-06-30 17:08:47 -0700662 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800663 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
664 final int listNavWidth = mListNavLayout.getMeasuredWidth();
665 availableWidth -= listNavWidth;
666 leftOfCenter -= listNavWidth;
Adam Powell33b97432010-04-20 10:01:14 -0700667 }
668 break;
Adam Powell661c9082010-07-02 10:09:44 -0700669 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powell2b6230e2010-09-07 17:55:25 -0700670 if (mTabScrollView != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800671 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
672 availableWidth -= itemPaddingSize;
673 leftOfCenter -= itemPaddingSize;
Adam Powell2b6230e2010-09-07 17:55:25 -0700674 mTabScrollView.measure(
Adam Powell661c9082010-07-02 10:09:44 -0700675 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
Adam Powellca259f42010-09-08 01:21:42 -0700676 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
Adam Powell9ab97872010-10-26 21:47:29 -0700677 final int tabWidth = mTabScrollView.getMeasuredWidth();
678 availableWidth -= tabWidth;
679 leftOfCenter -= tabWidth;
Adam Powell661c9082010-07-02 10:09:44 -0700680 }
681 break;
Adam Powell33b97432010-04-20 10:01:14 -0700682 }
683
Adam Powell6af97e12010-11-11 21:11:53 -0800684 if (mIndeterminateProgressView != null &&
685 mIndeterminateProgressView.getVisibility() != GONE) {
686 availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
687 childSpecHeight, 0);
688 rightOfCenter -= mIndeterminateProgressView.getMeasuredWidth();
689 }
690
Adam Powell9ab97872010-10-26 21:47:29 -0700691 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
692 final LayoutParams lp = generateLayoutParams(mCustomNavView.getLayoutParams());
693 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
694 (ActionBar.LayoutParams) lp : null;
695
696 int horizontalMargin = 0;
697 int verticalMargin = 0;
698 if (ablp != null) {
699 horizontalMargin = ablp.leftMargin + ablp.rightMargin;
700 verticalMargin = ablp.topMargin + ablp.bottomMargin;
701 }
702
703 // If the action bar is wrapping to its content height, don't allow a custom
704 // view to MATCH_PARENT.
705 int customNavHeightMode;
706 if (mContentHeight <= 0) {
707 customNavHeightMode = MeasureSpec.AT_MOST;
708 } else {
709 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
710 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
711 }
712 final int customNavHeight = Math.max(0,
713 (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
714
715 final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
716 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
717 int customNavWidth = Math.max(0,
718 (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
719 - horizontalMargin);
720 final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
721 Gravity.HORIZONTAL_GRAVITY_MASK;
722
723 // Centering a custom view is treated specially; we try to center within the whole
724 // action bar rather than in the available space.
725 if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
726 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
727 }
728
729 mCustomNavView.measure(
730 MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
731 MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
732 }
733
Adam Powelle2194442010-08-12 18:13:03 -0700734 if (mContentHeight <= 0) {
735 int measuredHeight = 0;
736 final int count = getChildCount();
737 for (int i = 0; i < count; i++) {
738 View v = getChildAt(i);
739 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
740 if (paddedViewHeight > measuredHeight) {
741 measuredHeight = paddedViewHeight;
742 }
743 }
744 setMeasuredDimension(contentWidth, measuredHeight);
745 } else {
746 setMeasuredDimension(contentWidth, maxHeight);
747 }
748
749 if (mContextView != null) {
750 mContextView.setHeight(getMeasuredHeight());
751 }
Adam Powell6af97e12010-11-11 21:11:53 -0800752
753 if (mProgressView != null && mProgressView.getVisibility() != GONE) {
754 mProgressView.measure(MeasureSpec.makeMeasureSpec(
755 contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
756 MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
757 }
Adam Powell33b97432010-04-20 10:01:14 -0700758 }
759
760 private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) {
Adam Powella1700782010-05-13 13:27:35 -0700761 child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
Adam Powell33b97432010-04-20 10:01:14 -0700762 childSpecHeight);
763
764 availableWidth -= child.getMeasuredWidth();
765 availableWidth -= spacing;
766
767 return availableWidth;
768 }
769
770 @Override
771 protected void onLayout(boolean changed, int l, int t, int r, int b) {
772 int x = getPaddingLeft();
773 final int y = getPaddingTop();
774 final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
775
Adam Powell9ab97872010-10-26 21:47:29 -0700776 if (mHomeLayout.getVisibility() != GONE) {
777 x += positionChild(mHomeLayout, x, y, contentHeight);
Adam Powell33b97432010-04-20 10:01:14 -0700778 }
779
Adam Powell2a7ea672011-01-23 20:25:15 -0800780 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800781 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
782 if (showTitle) {
Adam Powell9ab97872010-10-26 21:47:29 -0700783 x += positionChild(mTitleLayout, x, y, contentHeight);
784 }
785
Adam Powell33b97432010-04-20 10:01:14 -0700786 switch (mNavigationMode) {
Adam Powella4082912010-06-04 18:34:02 -0700787 case ActionBar.NAVIGATION_MODE_STANDARD:
Adam Powell33b97432010-04-20 10:01:14 -0700788 break;
Adam Powell9ab97872010-10-26 21:47:29 -0700789 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800790 if (mListNavLayout != null) {
791 if (showTitle) x += mItemPadding;
792 x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
Adam Powella4082912010-06-04 18:34:02 -0700793 }
794 break;
Adam Powell661c9082010-07-02 10:09:44 -0700795 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powell2b6230e2010-09-07 17:55:25 -0700796 if (mTabScrollView != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800797 if (showTitle) x += mItemPadding;
798 x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
Adam Powell661c9082010-07-02 10:09:44 -0700799 }
Adam Powell6af97e12010-11-11 21:11:53 -0800800 break;
Adam Powell33b97432010-04-20 10:01:14 -0700801 }
802
Adam Powell9ab97872010-10-26 21:47:29 -0700803 int menuLeft = r - l - getPaddingRight();
Adam Powell96675b12010-06-10 18:58:59 -0700804 if (mMenuView != null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700805 positionChildInverse(mMenuView, menuLeft, y, contentHeight);
806 menuLeft -= mMenuView.getMeasuredWidth();
807 }
808
Adam Powell6af97e12010-11-11 21:11:53 -0800809 if (mIndeterminateProgressView != null &&
810 mIndeterminateProgressView.getVisibility() != GONE) {
811 positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight);
812 menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
813 }
814
Adam Powell9ab97872010-10-26 21:47:29 -0700815 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
816 LayoutParams lp = mCustomNavView.getLayoutParams();
817 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
818 (ActionBar.LayoutParams) lp : null;
819
820 final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
821 final int navWidth = mCustomNavView.getMeasuredWidth();
822
823 int topMargin = 0;
824 int bottomMargin = 0;
825 if (ablp != null) {
826 x += ablp.leftMargin;
827 menuLeft -= ablp.rightMargin;
828 topMargin = ablp.topMargin;
829 bottomMargin = ablp.bottomMargin;
830 }
831
832 int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
833 // See if we actually have room to truly center; if not push against left or right.
834 if (hgravity == Gravity.CENTER_HORIZONTAL) {
835 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
836 if (centeredLeft < x) {
837 hgravity = Gravity.LEFT;
838 } else if (centeredLeft + navWidth > menuLeft) {
839 hgravity = Gravity.RIGHT;
840 }
841 }
842
843 int xpos = 0;
844 switch (hgravity) {
845 case Gravity.CENTER_HORIZONTAL:
846 xpos = ((mRight - mLeft) - navWidth) / 2;
847 break;
848 case Gravity.LEFT:
849 xpos = x;
850 break;
851 case Gravity.RIGHT:
852 xpos = menuLeft - navWidth;
853 break;
854 }
855
856 int ypos = 0;
857 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
858 case Gravity.CENTER_VERTICAL:
Jeff Sharkeyf7868052010-11-04 12:42:18 -0700859 final int paddedTop = mTop + getPaddingTop();
860 final int paddedBottom = mBottom - getPaddingBottom();
861 ypos = ((paddedBottom - paddedTop) - mCustomNavView.getMeasuredHeight()) / 2;
Adam Powell9ab97872010-10-26 21:47:29 -0700862 break;
863 case Gravity.TOP:
864 ypos = getPaddingTop() + topMargin;
865 break;
866 case Gravity.BOTTOM:
867 ypos = getHeight() - getPaddingBottom() - mCustomNavView.getMeasuredHeight()
868 - bottomMargin;
869 break;
870 }
871 x += positionChild(mCustomNavView, xpos, ypos, contentHeight);
Adam Powell33b97432010-04-20 10:01:14 -0700872 }
Adam Powell6af97e12010-11-11 21:11:53 -0800873
874 if (mProgressView != null) {
875 mProgressView.bringToFront();
876 final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
877 mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
878 mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
879 }
Adam Powell33b97432010-04-20 10:01:14 -0700880 }
881
882 private int positionChild(View child, int x, int y, int contentHeight) {
883 int childWidth = child.getMeasuredWidth();
884 int childHeight = child.getMeasuredHeight();
885 int childTop = y + (contentHeight - childHeight) / 2;
886
887 child.layout(x, childTop, x + childWidth, childTop + childHeight);
888
889 return childWidth;
890 }
891
892 private int positionChildInverse(View child, int x, int y, int contentHeight) {
893 int childWidth = child.getMeasuredWidth();
894 int childHeight = child.getMeasuredHeight();
895 int childTop = y + (contentHeight - childHeight) / 2;
896
897 child.layout(x - childWidth, childTop, x, childTop + childHeight);
898
899 return childWidth;
900 }
Adam Powell661c9082010-07-02 10:09:44 -0700901
902 private static class TabView extends LinearLayout {
903 private ActionBar.Tab mTab;
904
905 public TabView(Context context, ActionBar.Tab tab) {
Adam Powellca259f42010-09-08 01:21:42 -0700906 super(context, null, com.android.internal.R.attr.actionBarTabStyle);
Adam Powell661c9082010-07-02 10:09:44 -0700907 mTab = tab;
908
Adam Powell2b6230e2010-09-07 17:55:25 -0700909 final View custom = tab.getCustomView();
910 if (custom != null) {
911 addView(custom);
912 } else {
913 // TODO Style tabs based on the theme
Adam Powell661c9082010-07-02 10:09:44 -0700914
Adam Powell2b6230e2010-09-07 17:55:25 -0700915 final Drawable icon = tab.getIcon();
916 final CharSequence text = tab.getText();
Adam Powell661c9082010-07-02 10:09:44 -0700917
Adam Powell2b6230e2010-09-07 17:55:25 -0700918 if (icon != null) {
919 ImageView iconView = new ImageView(context);
920 iconView.setImageDrawable(icon);
921 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
922 LayoutParams.WRAP_CONTENT);
923 lp.gravity = Gravity.CENTER_VERTICAL;
924 iconView.setLayoutParams(lp);
925 addView(iconView);
926 }
Adam Powell661c9082010-07-02 10:09:44 -0700927
Adam Powell2b6230e2010-09-07 17:55:25 -0700928 if (text != null) {
Adam Powellca259f42010-09-08 01:21:42 -0700929 TextView textView = new TextView(context, null,
930 com.android.internal.R.attr.actionBarTabTextStyle);
Adam Powell2b6230e2010-09-07 17:55:25 -0700931 textView.setText(text);
932 textView.setSingleLine();
933 textView.setEllipsize(TruncateAt.END);
934 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
935 LayoutParams.WRAP_CONTENT);
936 lp.gravity = Gravity.CENTER_VERTICAL;
937 textView.setLayoutParams(lp);
938 addView(textView);
939 }
Adam Powell661c9082010-07-02 10:09:44 -0700940 }
941
942 setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
943 LayoutParams.MATCH_PARENT, 1));
944 }
945
946 public ActionBar.Tab getTab() {
947 return mTab;
948 }
949 }
950
951 private class TabClickListener implements OnClickListener {
952 public void onClick(View view) {
953 TabView tabView = (TabView) view;
954 tabView.getTab().select();
955 final int tabCount = mTabLayout.getChildCount();
956 for (int i = 0; i < tabCount; i++) {
957 final View child = mTabLayout.getChildAt(i);
958 child.setSelected(child == view);
959 }
960 }
961 }
Adam Powell2b0952b2011-03-09 00:15:38 -0800962
963 private static class HomeView extends FrameLayout {
964 private View mUpView;
965 private View mIconView;
966
967 public HomeView(Context context) {
968 this(context, null);
969 }
970
971 public HomeView(Context context, AttributeSet attrs) {
972 super(context, attrs);
973 }
974
975 @Override
976 protected void onFinishInflate() {
977 mUpView = findViewById(com.android.internal.R.id.up);
978 mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
979 }
980
981 @Override
982 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
983 measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
984 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
985 int width = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
986 int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
987 measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
988 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
989 width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
990 height = Math.max(height,
991 iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
992 setMeasuredDimension(width, height);
993 }
994
995 @Override
996 protected void onLayout(boolean changed, int l, int t, int r, int b) {
997 final int vCenter = (b - t) / 2;
998 int width = r - l;
999 if (mUpView.getVisibility() != GONE) {
1000 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1001 final int upHeight = mUpView.getMeasuredHeight();
1002 final int upWidth = mUpView.getMeasuredWidth();
1003 final int upTop = t + vCenter - upHeight / 2;
1004 mUpView.layout(l, upTop, l + upWidth, upTop + upHeight);
1005 final int upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
1006 width -= upOffset;
1007 l += upOffset;
1008 }
1009 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1010 final int iconHeight = mIconView.getMeasuredHeight();
1011 final int iconWidth = mIconView.getMeasuredWidth();
1012 final int hCenter = (r - l) / 2;
1013 final int iconLeft = l + iconLp.leftMargin + hCenter - iconWidth / 2;
1014 final int iconTop = t + iconLp.topMargin + vCenter - iconHeight / 2;
1015 mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
1016 }
1017 }
Adam Powell33b97432010-04-20 10:01:14 -07001018}