blob: 13ccbba3af645570cd8871c4aa098af0016d2698 [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 Powell696cba52011-03-29 10:38:16 -070021import com.android.internal.view.menu.ActionMenuPresenter;
Adam Powell7ade1be2010-06-17 12:51:21 -070022import com.android.internal.view.menu.ActionMenuView;
Adam Powell96675b12010-06-10 18:58:59 -070023import com.android.internal.view.menu.MenuBuilder;
Adam Powell696cba52011-03-29 10:38:16 -070024import com.android.internal.view.menu.MenuPresenter;
Adam Powell33b97432010-04-20 10:01:14 -070025
26import android.app.ActionBar;
Adam Powell8515ee82010-11-30 14:09:55 -080027import android.app.ActionBar.OnNavigationListener;
Adam Powell9146ac72010-08-16 18:53:38 -070028import android.app.Activity;
Adam Powell33b97432010-04-20 10:01:14 -070029import android.content.Context;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
Adam Powell9ab97872010-10-26 21:47:29 -070032import android.content.pm.PackageManager.NameNotFoundException;
Adam Powell45c515b2011-04-21 18:50:20 -070033import android.content.res.Resources;
Adam Powell33b97432010-04-20 10:01:14 -070034import android.content.res.TypedArray;
Adam Powell33b97432010-04-20 10:01:14 -070035import android.graphics.drawable.Drawable;
Adam Powell2a7ea672011-01-23 20:25:15 -080036import android.text.TextUtils;
Adam Powell661c9082010-07-02 10:09:44 -070037import android.text.TextUtils.TruncateAt;
Adam Powell33b97432010-04-20 10:01:14 -070038import android.util.AttributeSet;
Adam Powell45c515b2011-04-21 18:50:20 -070039import android.util.DisplayMetrics;
Adam Powell9ab97872010-10-26 21:47:29 -070040import android.util.Log;
Adam Powell661c9082010-07-02 10:09:44 -070041import android.view.Gravity;
Adam Powell89e06452010-06-23 20:24:52 -070042import android.view.LayoutInflater;
43import android.view.Menu;
44import android.view.View;
45import android.view.ViewGroup;
Adam Powell9ab97872010-10-26 21:47:29 -070046import android.view.ViewParent;
Adam Powell8d12e202010-11-15 16:44:17 -080047import android.view.Window;
Adam Powella4082912010-06-04 18:34:02 -070048import android.widget.AdapterView;
Adam Powell2b0952b2011-03-09 00:15:38 -080049import android.widget.FrameLayout;
Adam Powell2b6230e2010-09-07 17:55:25 -070050import android.widget.HorizontalScrollView;
Adam Powell33b97432010-04-20 10:01:14 -070051import android.widget.ImageView;
Adam Powell0e94b512010-06-29 17:58:20 -070052import android.widget.LinearLayout;
Adam Powell6af97e12010-11-11 21:11:53 -080053import android.widget.ProgressBar;
Adam Powella4082912010-06-04 18:34:02 -070054import android.widget.Spinner;
55import android.widget.SpinnerAdapter;
Adam Powell33b97432010-04-20 10:01:14 -070056import android.widget.TextView;
57
Adam Powell33b97432010-04-20 10:01:14 -070058/**
59 * @hide
60 */
Adam Powell640a66e2011-04-29 10:18:53 -070061public class ActionBarView extends AbsActionBarView {
Adam Powell33b97432010-04-20 10:01:14 -070062 private static final String TAG = "ActionBarView";
Adam Powellbe4d68e2010-10-08 18:16:34 -070063
Adam Powell33b97432010-04-20 10:01:14 -070064 /**
65 * Display options applied by default
66 */
67 public static final int DISPLAY_DEFAULT = 0;
68
69 /**
70 * Display options that require re-layout as opposed to a simple invalidate
71 */
Adam Powella1700782010-05-13 13:27:35 -070072 private static final int DISPLAY_RELAYOUT_MASK =
Adam Powell9ab97872010-10-26 21:47:29 -070073 ActionBar.DISPLAY_SHOW_HOME |
74 ActionBar.DISPLAY_USE_LOGO |
75 ActionBar.DISPLAY_HOME_AS_UP |
76 ActionBar.DISPLAY_SHOW_CUSTOM |
77 ActionBar.DISPLAY_SHOW_TITLE;
78
79 private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
Adam Powell33b97432010-04-20 10:01:14 -070080
81 private final int mContentHeight;
82
83 private int mNavigationMode;
Adam Powell9ab97872010-10-26 21:47:29 -070084 private int mDisplayOptions = ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP;
Adam Powell33b97432010-04-20 10:01:14 -070085 private CharSequence mTitle;
86 private CharSequence mSubtitle;
87 private Drawable mIcon;
88 private Drawable mLogo;
Adam Powell33b97432010-04-20 10:01:14 -070089
Ed Heyl1c603002010-11-18 12:18:23 -080090 private View mHomeLayout;
91 private View mHomeAsUpView;
Adam Powell33b97432010-04-20 10:01:14 -070092 private ImageView mIconView;
Adam Powell0e94b512010-06-29 17:58:20 -070093 private LinearLayout mTitleLayout;
Adam Powell33b97432010-04-20 10:01:14 -070094 private TextView mTitleView;
95 private TextView mSubtitleView;
Adam Powella4082912010-06-04 18:34:02 -070096 private Spinner mSpinner;
Adam Powell3f7f7ac2010-12-05 16:44:38 -080097 private LinearLayout mListNavLayout;
Adam Powell2b6230e2010-09-07 17:55:25 -070098 private HorizontalScrollView mTabScrollView;
Adam Powelldae78242011-04-25 15:23:41 -070099 private ViewGroup mTabLayout;
Adam Powella4082912010-06-04 18:34:02 -0700100 private View mCustomNavView;
Adam Powell6af97e12010-11-11 21:11:53 -0800101 private ProgressBar mProgressView;
102 private ProgressBar mIndeterminateProgressView;
103
104 private int mProgressBarPadding;
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800105 private int mItemPadding;
Adam Powell33b97432010-04-20 10:01:14 -0700106
Adam Powelle2194442010-08-12 18:13:03 -0700107 private int mTitleStyleRes;
108 private int mSubtitleStyleRes;
Adam Powell6af97e12010-11-11 21:11:53 -0800109 private int mProgressStyle;
110 private int mIndeterminateProgressStyle;
Adam Powelle2194442010-08-12 18:13:03 -0700111
Adam Powell9b4bee02011-04-27 19:24:47 -0700112 private boolean mSplitActionBar;
Adam Powelle92ea342010-07-14 14:45:50 -0700113 private boolean mUserTitle;
Adam Powelldae78242011-04-25 15:23:41 -0700114 private boolean mIncludeTabs;
Adam Powell33b97432010-04-20 10:01:14 -0700115
Adam Powell96675b12010-06-10 18:58:59 -0700116 private MenuBuilder mOptionsMenu;
Adam Powell96675b12010-06-10 18:58:59 -0700117
Adam Powelle2194442010-08-12 18:13:03 -0700118 private ActionBarContextView mContextView;
119
Adam Powell33b97432010-04-20 10:01:14 -0700120 private ActionMenuItem mLogoNavItem;
Adam Powell9ab97872010-10-26 21:47:29 -0700121
122 private SpinnerAdapter mSpinnerAdapter;
Adam Powell8515ee82010-11-30 14:09:55 -0800123 private OnNavigationListener mCallback;
Adam Powell33b97432010-04-20 10:01:14 -0700124
Adam Powella4082912010-06-04 18:34:02 -0700125 private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
126 new AdapterView.OnItemSelectedListener() {
127 public void onItemSelected(AdapterView parent, View view, int position, long id) {
128 if (mCallback != null) {
129 mCallback.onNavigationItemSelected(position, id);
130 }
131 }
132 public void onNothingSelected(AdapterView parent) {
133 // Do nothing
134 }
135 };
136
Adam Powell2b6230e2010-09-07 17:55:25 -0700137 private OnClickListener mTabClickListener = null;
138
Adam Powell33b97432010-04-20 10:01:14 -0700139 public ActionBarView(Context context, AttributeSet attrs) {
140 super(context, attrs);
141
Adam Powell654e4e42011-01-03 16:33:50 -0800142 // Background is always provided by the container.
143 setBackgroundResource(0);
144
Adam Powell33b97432010-04-20 10:01:14 -0700145 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
146
Adam Powell9ab97872010-10-26 21:47:29 -0700147 ApplicationInfo appInfo = context.getApplicationInfo();
Adam Powell33b97432010-04-20 10:01:14 -0700148 PackageManager pm = context.getPackageManager();
Adam Powell661c9082010-07-02 10:09:44 -0700149 mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode,
150 ActionBar.NAVIGATION_MODE_STANDARD);
Adam Powell33b97432010-04-20 10:01:14 -0700151 mTitle = a.getText(R.styleable.ActionBar_title);
152 mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
Adam Powell33b97432010-04-20 10:01:14 -0700153
154 mLogo = a.getDrawable(R.styleable.ActionBar_logo);
155 if (mLogo == null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700156 if (context instanceof Activity) {
157 try {
158 mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
159 } catch (NameNotFoundException e) {
160 Log.e(TAG, "Activity component name not found!", e);
161 }
162 }
163 if (mLogo == null) {
164 mLogo = appInfo.loadLogo(pm);
165 }
Adam Powell33b97432010-04-20 10:01:14 -0700166 }
Adam Powell9ab97872010-10-26 21:47:29 -0700167
Adam Powell33b97432010-04-20 10:01:14 -0700168 mIcon = a.getDrawable(R.styleable.ActionBar_icon);
169 if (mIcon == null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700170 if (context instanceof Activity) {
171 try {
172 mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
173 } catch (NameNotFoundException e) {
174 Log.e(TAG, "Activity component name not found!", e);
175 }
176 }
177 if (mIcon == null) {
178 mIcon = appInfo.loadIcon(pm);
179 }
Adam Powell33b97432010-04-20 10:01:14 -0700180 }
Adam Powell9ab97872010-10-26 21:47:29 -0700181
Ed Heyl1c603002010-11-18 12:18:23 -0800182 final LayoutInflater inflater = LayoutInflater.from(context);
Adam Powell9ab97872010-10-26 21:47:29 -0700183
Ed Heyl1c603002010-11-18 12:18:23 -0800184 final int homeResId = a.getResourceId(
Adam Powellb33be1c2010-11-18 12:11:40 -0800185 com.android.internal.R.styleable.ActionBar_homeLayout,
186 com.android.internal.R.layout.action_bar_home);
Adam Powell9ab97872010-10-26 21:47:29 -0700187
Ed Heyl1c603002010-11-18 12:18:23 -0800188 mHomeLayout = inflater.inflate(homeResId, this, false);
189
190 mHomeAsUpView = mHomeLayout.findViewById(com.android.internal.R.id.up);
191 mIconView = (ImageView) mHomeLayout.findViewById(com.android.internal.R.id.home);
Adam Powell33b97432010-04-20 10:01:14 -0700192
Adam Powelle2194442010-08-12 18:13:03 -0700193 mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
194 mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
Adam Powell6af97e12010-11-11 21:11:53 -0800195 mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
196 mIndeterminateProgressStyle = a.getResourceId(
197 R.styleable.ActionBar_indeterminateProgressStyle, 0);
198
199 mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800200 mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
Adam Powelle2194442010-08-12 18:13:03 -0700201
Adam Powelldae78242011-04-25 15:23:41 -0700202 mIncludeTabs = a.getBoolean(R.styleable.ActionBar_embeddedTabs, true);
203
Adam Powell9ab97872010-10-26 21:47:29 -0700204 setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
205
Adam Powell33b97432010-04-20 10:01:14 -0700206 final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
207 if (customNavId != 0) {
Ed Heyl1c603002010-11-18 12:18:23 -0800208 mCustomNavView = (View) inflater.inflate(customNavId, this, false);
Adam Powell9ab97872010-10-26 21:47:29 -0700209 mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
210 setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
Adam Powell33b97432010-04-20 10:01:14 -0700211 }
212
Adam Powelle2194442010-08-12 18:13:03 -0700213 mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
Adam Powellbe4d68e2010-10-08 18:16:34 -0700214
Adam Powell33b97432010-04-20 10:01:14 -0700215 a.recycle();
Adam Powell33b97432010-04-20 10:01:14 -0700216
Ben Komaload199ec2010-11-01 12:24:16 -0700217 mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
218 mHomeLayout.setOnClickListener(new OnClickListener() {
Adam Powellb33be1c2010-11-18 12:11:40 -0800219 public void onClick(View v) {
220 Context context = getContext();
221 if (context instanceof Activity) {
222 Activity activity = (Activity) context;
223 activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
224 }
Ben Komaload199ec2010-11-01 12:24:16 -0700225 }
Ben Komaload199ec2010-11-01 12:24:16 -0700226 });
227 mHomeLayout.setClickable(true);
228 mHomeLayout.setFocusable(true);
Adam Powell33b97432010-04-20 10:01:14 -0700229 }
Adam Powella7db0372010-06-30 17:08:47 -0700230
Patrick Dubroye0a799a2011-05-04 16:19:22 -0700231 @Override
232 public boolean shouldDelayChildPressedState() {
233 return false;
234 }
235
Adam Powell6af97e12010-11-11 21:11:53 -0800236 public void initProgress() {
237 mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle);
238 mProgressView.setId(R.id.progress_horizontal);
239 mProgressView.setMax(10000);
240 addView(mProgressView);
241 }
242
243 public void initIndeterminateProgress() {
244 mIndeterminateProgressView = new ProgressBar(mContext, null, 0,
245 mIndeterminateProgressStyle);
246 mIndeterminateProgressView.setId(R.id.progress_circular);
247 addView(mIndeterminateProgressView);
248 }
249
Adam Powell9b4bee02011-04-27 19:24:47 -0700250 public void setSplitActionBar(boolean splitActionBar) {
251 if (mSplitActionBar != splitActionBar) {
252 if (mMenuView != null) {
253 if (splitActionBar) {
254 removeView(mMenuView);
255 if (mSplitView != null) {
256 mSplitView.addView(mMenuView);
257 }
258 } else {
259 addView(mMenuView);
260 }
261 }
262 mSplitActionBar = splitActionBar;
263 }
264 }
265
266 public boolean isSplitActionBar() {
267 return mSplitActionBar;
268 }
269
Adam Powelldae78242011-04-25 15:23:41 -0700270 public boolean hasEmbeddedTabs() {
271 return mIncludeTabs;
272 }
273
274 public void setExternalTabLayout(ViewGroup tabLayout) {
275 mTabLayout = tabLayout;
276 }
277
Adam Powell8515ee82010-11-30 14:09:55 -0800278 public void setCallback(OnNavigationListener callback) {
Adam Powell96675b12010-06-10 18:58:59 -0700279 mCallback = callback;
Adam Powell33b97432010-04-20 10:01:14 -0700280 }
Adam Powella7db0372010-06-30 17:08:47 -0700281
Adam Powell696cba52011-03-29 10:38:16 -0700282 public void setMenu(Menu menu, MenuPresenter.Callback cb) {
Adam Powellf2d7a5d2011-02-07 18:05:24 -0800283 if (menu == mOptionsMenu) return;
284
Adam Powell696cba52011-03-29 10:38:16 -0700285 if (mOptionsMenu != null) {
Adam Powell640a66e2011-04-29 10:18:53 -0700286 mOptionsMenu.removeMenuPresenter(mMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -0700287 }
288
Adam Powell96675b12010-06-10 18:58:59 -0700289 MenuBuilder builder = (MenuBuilder) menu;
290 mOptionsMenu = builder;
291 if (mMenuView != null) {
292 removeView(mMenuView);
Adam Powell33b97432010-04-20 10:01:14 -0700293 }
Adam Powell640a66e2011-04-29 10:18:53 -0700294 if (mMenuPresenter == null) {
295 mMenuPresenter = new ActionMenuPresenter();
296 mMenuPresenter.setCallback(cb);
297 builder.addMenuPresenter(mMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -0700298 }
Adam Powell640a66e2011-04-29 10:18:53 -0700299 final ActionMenuView menuView = (ActionMenuView) mMenuPresenter.getMenuView(this);
Adam Powell96675b12010-06-10 18:58:59 -0700300 final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
301 LayoutParams.MATCH_PARENT);
302 menuView.setLayoutParams(layoutParams);
Adam Powell9b4bee02011-04-27 19:24:47 -0700303 if (!mSplitActionBar) {
304 addView(menuView);
305 } else {
306 // Allow full screen width in split mode.
Adam Powell640a66e2011-04-29 10:18:53 -0700307 mMenuPresenter.setWidthLimit(
308 getContext().getResources().getDisplayMetrics().widthPixels, true);
Adam Powell9b4bee02011-04-27 19:24:47 -0700309 // No limit to the item count; use whatever will fit.
Adam Powell640a66e2011-04-29 10:18:53 -0700310 mMenuPresenter.setItemLimit(Integer.MAX_VALUE);
311 // Span the whole width
312 layoutParams.width = LayoutParams.MATCH_PARENT;
Adam Powell9b4bee02011-04-27 19:24:47 -0700313 if (mSplitView != null) {
314 mSplitView.addView(menuView);
315 } // We'll add this later if we missed it this time.
316 }
Adam Powell96675b12010-06-10 18:58:59 -0700317 mMenuView = menuView;
Adam Powell33b97432010-04-20 10:01:14 -0700318 }
Adam Powella7db0372010-06-30 17:08:47 -0700319
Adam Powell33b97432010-04-20 10:01:14 -0700320 public void setCustomNavigationView(View view) {
Adam Powell9ab97872010-10-26 21:47:29 -0700321 final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
322 if (mCustomNavView != null && showCustom) {
323 removeView(mCustomNavView);
324 }
Adam Powella4082912010-06-04 18:34:02 -0700325 mCustomNavView = view;
Adam Powell9ab97872010-10-26 21:47:29 -0700326 if (mCustomNavView != null && showCustom) {
327 addView(mCustomNavView);
Adam Powell33b97432010-04-20 10:01:14 -0700328 }
Adam Powell33b97432010-04-20 10:01:14 -0700329 }
Adam Powella7db0372010-06-30 17:08:47 -0700330
Adam Powell33b97432010-04-20 10:01:14 -0700331 public CharSequence getTitle() {
332 return mTitle;
333 }
Adam Powella7db0372010-06-30 17:08:47 -0700334
Adam Powelle92ea342010-07-14 14:45:50 -0700335 /**
336 * Set the action bar title. This will always replace or override window titles.
337 * @param title Title to set
338 *
339 * @see #setWindowTitle(CharSequence)
340 */
Adam Powell33b97432010-04-20 10:01:14 -0700341 public void setTitle(CharSequence title) {
Adam Powelle92ea342010-07-14 14:45:50 -0700342 mUserTitle = true;
343 setTitleImpl(title);
344 }
345
346 /**
347 * Set the window title. A window title will always be replaced or overridden by a user title.
348 * @param title Title to set
349 *
350 * @see #setTitle(CharSequence)
351 */
352 public void setWindowTitle(CharSequence title) {
353 if (!mUserTitle) {
354 setTitleImpl(title);
355 }
356 }
357
358 private void setTitleImpl(CharSequence title) {
Adam Powell33b97432010-04-20 10:01:14 -0700359 mTitle = title;
360 if (mTitleView != null) {
361 mTitleView.setText(title);
Adam Powell2a7ea672011-01-23 20:25:15 -0800362 mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ?
363 GONE : VISIBLE);
Adam Powell33b97432010-04-20 10:01:14 -0700364 }
365 if (mLogoNavItem != null) {
366 mLogoNavItem.setTitle(title);
367 }
368 }
Adam Powella7db0372010-06-30 17:08:47 -0700369
Adam Powell33b97432010-04-20 10:01:14 -0700370 public CharSequence getSubtitle() {
371 return mSubtitle;
372 }
Adam Powella7db0372010-06-30 17:08:47 -0700373
Adam Powell33b97432010-04-20 10:01:14 -0700374 public void setSubtitle(CharSequence subtitle) {
375 mSubtitle = subtitle;
376 if (mSubtitleView != null) {
377 mSubtitleView.setText(subtitle);
Adam Powell04587962010-11-11 22:15:07 -0800378 mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
Adam Powell2a7ea672011-01-23 20:25:15 -0800379 mTitleLayout.setVisibility(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle) ?
380 GONE : VISIBLE);
Adam Powell33b97432010-04-20 10:01:14 -0700381 }
382 }
Adam Powella7db0372010-06-30 17:08:47 -0700383
Adam Powell33b97432010-04-20 10:01:14 -0700384 public void setDisplayOptions(int options) {
Adam Powella1700782010-05-13 13:27:35 -0700385 final int flagsChanged = options ^ mDisplayOptions;
Adam Powell33b97432010-04-20 10:01:14 -0700386 mDisplayOptions = options;
Adam Powelldae78242011-04-25 15:23:41 -0700387
388 if ((flagsChanged & ActionBar.DISPLAY_DISABLE_HOME) != 0) {
389 final boolean disableHome = (options & ActionBar.DISPLAY_DISABLE_HOME) != 0;
390 mHomeLayout.setEnabled(!disableHome);
391 }
392
Adam Powell33b97432010-04-20 10:01:14 -0700393 if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
Adam Powell9ab97872010-10-26 21:47:29 -0700394 final int vis = (options & ActionBar.DISPLAY_SHOW_HOME) != 0 ? VISIBLE : GONE;
395 mHomeLayout.setVisibility(vis);
396
397 if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
Adam Powellf3cd1d92011-04-26 17:31:52 -0700398 final boolean isUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
399 mHomeAsUpView.setVisibility(isUp ? VISIBLE : GONE);
Adam Powella1700782010-05-13 13:27:35 -0700400 }
Adam Powell9ab97872010-10-26 21:47:29 -0700401
Ed Heyl1c603002010-11-18 12:18:23 -0800402 if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
403 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
404 mIconView.setImageDrawable(logoVis ? mLogo : mIcon);
Adam Powell9ab97872010-10-26 21:47:29 -0700405 }
406
407 if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
408 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
409 initTitle();
410 } else {
411 removeView(mTitleLayout);
412 }
413 }
414
415 if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
416 if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
417 addView(mCustomNavView);
418 } else {
419 removeView(mCustomNavView);
420 }
Adam Powella1700782010-05-13 13:27:35 -0700421 }
422
Adam Powell33b97432010-04-20 10:01:14 -0700423 requestLayout();
424 } else {
425 invalidate();
426 }
Adam Powellf3cd1d92011-04-26 17:31:52 -0700427
428 // Make sure the home button has an accurate content description for accessibility.
429 if ((options & ActionBar.DISPLAY_DISABLE_HOME) != 0) {
430 mHomeLayout.setContentDescription(null);
431 } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
432 mHomeLayout.setContentDescription(mContext.getResources().getText(
433 R.string.action_bar_up_description));
434 } else {
435 mHomeLayout.setContentDescription(mContext.getResources().getText(
436 R.string.action_bar_home_description));
437 }
Adam Powell33b97432010-04-20 10:01:14 -0700438 }
439
Adam Powell1969b872011-03-22 11:52:48 -0700440 public void setIcon(Drawable icon) {
441 mIcon = icon;
442 if (icon != null &&
443 ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) {
444 mIconView.setImageDrawable(icon);
445 }
446 }
447
Adam Powell45c515b2011-04-21 18:50:20 -0700448 public void setIcon(int resId) {
449 setIcon(mContext.getResources().getDrawableForDensity(resId, getPreferredIconDensity()));
450 }
451
Adam Powell1969b872011-03-22 11:52:48 -0700452 public void setLogo(Drawable logo) {
453 mLogo = logo;
454 if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
455 mIconView.setImageDrawable(logo);
456 }
457 }
458
Adam Powell45c515b2011-04-21 18:50:20 -0700459 public void setLogo(int resId) {
460 mContext.getResources().getDrawable(resId);
461 }
462
463 /**
464 * @return Drawable density to load that will best fit the available height.
465 */
466 private int getPreferredIconDensity() {
467 final Resources res = mContext.getResources();
468 final int availableHeight = getLayoutParams().height -
469 mIconView.getPaddingTop() - mIconView.getPaddingBottom();
470 int iconSize = res.getDimensionPixelSize(android.R.dimen.app_icon_size);
471
Adam Powelld0f650c2011-04-22 16:05:17 -0700472 if (iconSize * DisplayMetrics.DENSITY_LOW >= availableHeight) {
Adam Powell45c515b2011-04-21 18:50:20 -0700473 return DisplayMetrics.DENSITY_LOW;
Adam Powelld0f650c2011-04-22 16:05:17 -0700474 } else if (iconSize * DisplayMetrics.DENSITY_MEDIUM >= availableHeight) {
Adam Powell45c515b2011-04-21 18:50:20 -0700475 return DisplayMetrics.DENSITY_MEDIUM;
Adam Powelld0f650c2011-04-22 16:05:17 -0700476 } else if (iconSize * DisplayMetrics.DENSITY_HIGH >= availableHeight) {
Adam Powell45c515b2011-04-21 18:50:20 -0700477 return DisplayMetrics.DENSITY_HIGH;
478 }
479 return DisplayMetrics.DENSITY_XHIGH;
480 }
481
Adam Powell33b97432010-04-20 10:01:14 -0700482 public void setNavigationMode(int mode) {
Adam Powella1700782010-05-13 13:27:35 -0700483 final int oldMode = mNavigationMode;
484 if (mode != oldMode) {
485 switch (oldMode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700486 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powella4082912010-06-04 18:34:02 -0700487 if (mSpinner != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800488 removeView(mListNavLayout);
Adam Powella4082912010-06-04 18:34:02 -0700489 }
490 break;
Adam Powell661c9082010-07-02 10:09:44 -0700491 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powelldae78242011-04-25 15:23:41 -0700492 if (mTabScrollView != null) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700493 removeView(mTabScrollView);
Adam Powell661c9082010-07-02 10:09:44 -0700494 }
Adam Powella1700782010-05-13 13:27:35 -0700495 }
496
497 switch (mode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700498 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800499 if (mSpinner == null) {
500 mSpinner = new Spinner(mContext, null,
501 com.android.internal.R.attr.actionDropDownStyle);
502 mListNavLayout = new LinearLayout(mContext, null,
503 com.android.internal.R.attr.actionBarTabBarStyle);
504 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
Adam Powelle7d46842011-01-13 21:36:09 -0800505 LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800506 params.gravity = Gravity.CENTER;
507 mListNavLayout.addView(mSpinner, params);
508 }
509 if (mSpinner.getAdapter() != mSpinnerAdapter) {
510 mSpinner.setAdapter(mSpinnerAdapter);
511 }
Adam Powella4082912010-06-04 18:34:02 -0700512 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800513 addView(mListNavLayout);
Adam Powella4082912010-06-04 18:34:02 -0700514 break;
Adam Powell661c9082010-07-02 10:09:44 -0700515 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powell9ab97872010-10-26 21:47:29 -0700516 ensureTabsExist();
Adam Powelldae78242011-04-25 15:23:41 -0700517 if (mTabScrollView != null) {
518 addView(mTabScrollView);
519 }
Adam Powell661c9082010-07-02 10:09:44 -0700520 break;
Adam Powella1700782010-05-13 13:27:35 -0700521 }
Adam Powell33b97432010-04-20 10:01:14 -0700522 mNavigationMode = mode;
523 requestLayout();
524 }
525 }
526
Adam Powell9ab97872010-10-26 21:47:29 -0700527 private void ensureTabsExist() {
Adam Powelldae78242011-04-25 15:23:41 -0700528 if (!mIncludeTabs) return;
529
Adam Powell9ab97872010-10-26 21:47:29 -0700530 if (mTabScrollView == null) {
531 mTabScrollView = new HorizontalScrollView(getContext());
Adam Powellc18c38f2011-03-15 11:57:46 -0700532 mTabScrollView.setHorizontalFadingEdgeEnabled(true);
Adam Powelldae78242011-04-25 15:23:41 -0700533 mTabLayout = createTabContainer();
Adam Powell9ab97872010-10-26 21:47:29 -0700534 mTabScrollView.addView(mTabLayout);
535 }
536 }
537
Adam Powelldae78242011-04-25 15:23:41 -0700538 public ViewGroup createTabContainer() {
539 ViewGroup result = new LinearLayout(getContext(), null,
540 com.android.internal.R.attr.actionBarTabBarStyle);
541 result.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
542 mContentHeight));
543 return result;
544 }
545
Adam Powella4082912010-06-04 18:34:02 -0700546 public void setDropdownAdapter(SpinnerAdapter adapter) {
Adam Powell9ab97872010-10-26 21:47:29 -0700547 mSpinnerAdapter = adapter;
548 if (mSpinner != null) {
549 mSpinner.setAdapter(adapter);
550 }
551 }
552
553 public SpinnerAdapter getDropdownAdapter() {
554 return mSpinnerAdapter;
Adam Powella4082912010-06-04 18:34:02 -0700555 }
Adam Powell17809772010-07-21 13:25:11 -0700556
557 public void setDropdownSelectedPosition(int position) {
558 mSpinner.setSelection(position);
559 }
560
561 public int getDropdownSelectedPosition() {
562 return mSpinner.getSelectedItemPosition();
563 }
564
Adam Powell33b97432010-04-20 10:01:14 -0700565 public View getCustomNavigationView() {
Adam Powella4082912010-06-04 18:34:02 -0700566 return mCustomNavView;
Adam Powell33b97432010-04-20 10:01:14 -0700567 }
568
569 public int getNavigationMode() {
570 return mNavigationMode;
571 }
572
573 public int getDisplayOptions() {
574 return mDisplayOptions;
575 }
Adam Powella7db0372010-06-30 17:08:47 -0700576
Adam Powell661c9082010-07-02 10:09:44 -0700577 private TabView createTabView(ActionBar.Tab tab) {
578 final TabView tabView = new TabView(getContext(), tab);
579 tabView.setFocusable(true);
Adam Powell2b6230e2010-09-07 17:55:25 -0700580
581 if (mTabClickListener == null) {
582 mTabClickListener = new TabClickListener();
583 }
584 tabView.setOnClickListener(mTabClickListener);
Adam Powell661c9082010-07-02 10:09:44 -0700585 return tabView;
586 }
587
Adam Powell81b89442010-11-02 17:58:56 -0700588 public void addTab(ActionBar.Tab tab, boolean setSelected) {
Adam Powell9ab97872010-10-26 21:47:29 -0700589 ensureTabsExist();
Adam Powell2b6230e2010-09-07 17:55:25 -0700590 View tabView = createTabView(tab);
Adam Powell661c9082010-07-02 10:09:44 -0700591 mTabLayout.addView(tabView);
Adam Powell81b89442010-11-02 17:58:56 -0700592 if (setSelected) {
Adam Powell661c9082010-07-02 10:09:44 -0700593 tabView.setSelected(true);
594 }
595 }
596
Adam Powell81b89442010-11-02 17:58:56 -0700597 public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
Adam Powell9ab97872010-10-26 21:47:29 -0700598 ensureTabsExist();
Adam Powell661c9082010-07-02 10:09:44 -0700599 final TabView tabView = createTabView(tab);
600 mTabLayout.addView(tabView, position);
Adam Powell81b89442010-11-02 17:58:56 -0700601 if (setSelected) {
Adam Powell661c9082010-07-02 10:09:44 -0700602 tabView.setSelected(true);
603 }
604 }
605
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700606 public void updateTab(int position) {
607 ((TabView) mTabLayout.getChildAt(position)).update();
608 }
609
Adam Powell661c9082010-07-02 10:09:44 -0700610 public void removeTabAt(int position) {
Adam Powell9ab97872010-10-26 21:47:29 -0700611 if (mTabLayout != null) {
612 mTabLayout.removeViewAt(position);
613 }
Adam Powell661c9082010-07-02 10:09:44 -0700614 }
615
Adam Powell0c24a552010-11-03 16:44:11 -0700616 public void removeAllTabs() {
617 if (mTabLayout != null) {
618 mTabLayout.removeAllViews();
619 }
620 }
621
Adam Powella7db0372010-06-30 17:08:47 -0700622 @Override
623 protected LayoutParams generateDefaultLayoutParams() {
624 // Used by custom nav views if they don't supply layout params. Everything else
625 // added to an ActionBarView should have them already.
Adam Powell9ab97872010-10-26 21:47:29 -0700626 return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
Adam Powella7db0372010-06-30 17:08:47 -0700627 }
628
Adam Powell33b97432010-04-20 10:01:14 -0700629 @Override
630 protected void onFinishInflate() {
631 super.onFinishInflate();
632
Adam Powell9ab97872010-10-26 21:47:29 -0700633 addView(mHomeLayout);
634
Adam Powell9ab97872010-10-26 21:47:29 -0700635 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
636 final ViewParent parent = mCustomNavView.getParent();
637 if (parent != this) {
638 if (parent instanceof ViewGroup) {
639 ((ViewGroup) parent).removeView(mCustomNavView);
640 }
Adam Powella4082912010-06-04 18:34:02 -0700641 addView(mCustomNavView);
Adam Powell33b97432010-04-20 10:01:14 -0700642 }
Adam Powell33b97432010-04-20 10:01:14 -0700643 }
644 }
Adam Powella1700782010-05-13 13:27:35 -0700645
646 private void initTitle() {
647 LayoutInflater inflater = LayoutInflater.from(getContext());
Adam Powell0e94b512010-06-29 17:58:20 -0700648 mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
649 mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
650 mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
Adam Powelle2194442010-08-12 18:13:03 -0700651
652 if (mTitleStyleRes != 0) {
653 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
654 }
Adam Powella1700782010-05-13 13:27:35 -0700655 if (mTitle != null) {
656 mTitleView.setText(mTitle);
657 }
Adam Powelle2194442010-08-12 18:13:03 -0700658
659 if (mSubtitleStyleRes != 0) {
660 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
661 }
Adam Powell0e94b512010-06-29 17:58:20 -0700662 if (mSubtitle != null) {
663 mSubtitleView.setText(mSubtitle);
664 mSubtitleView.setVisibility(VISIBLE);
665 }
Adam Powelle2194442010-08-12 18:13:03 -0700666
Adam Powell0e94b512010-06-29 17:58:20 -0700667 addView(mTitleLayout);
Adam Powella1700782010-05-13 13:27:35 -0700668 }
Adam Powell33b97432010-04-20 10:01:14 -0700669
Adam Powell661c9082010-07-02 10:09:44 -0700670 public void setTabSelected(int position) {
Adam Powell9ab97872010-10-26 21:47:29 -0700671 ensureTabsExist();
Adam Powell661c9082010-07-02 10:09:44 -0700672 final int tabCount = mTabLayout.getChildCount();
673 for (int i = 0; i < tabCount; i++) {
674 final View child = mTabLayout.getChildAt(i);
675 child.setSelected(i == position);
676 }
677 }
678
Adam Powelle2194442010-08-12 18:13:03 -0700679 public void setContextView(ActionBarContextView view) {
680 mContextView = view;
681 }
682
Adam Powell33b97432010-04-20 10:01:14 -0700683 @Override
684 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
685 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
686 if (widthMode != MeasureSpec.EXACTLY) {
687 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
688 "with android:layout_width=\"match_parent\" (or fill_parent)");
689 }
690
691 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
692 if (heightMode != MeasureSpec.AT_MOST) {
693 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
694 "with android:layout_height=\"wrap_content\"");
695 }
696
697 int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
Adam Powelle2194442010-08-12 18:13:03 -0700698
699 int maxHeight = mContentHeight > 0 ?
700 mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
Adam Powell33b97432010-04-20 10:01:14 -0700701
Adam Powelle2194442010-08-12 18:13:03 -0700702 final int verticalPadding = getPaddingTop() + getPaddingBottom();
Adam Powell9ab97872010-10-26 21:47:29 -0700703 final int paddingLeft = getPaddingLeft();
704 final int paddingRight = getPaddingRight();
Adam Powelle2194442010-08-12 18:13:03 -0700705 final int height = maxHeight - verticalPadding;
Adam Powella1700782010-05-13 13:27:35 -0700706 final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
Adam Powell33b97432010-04-20 10:01:14 -0700707
Adam Powell9ab97872010-10-26 21:47:29 -0700708 int availableWidth = contentWidth - paddingLeft - paddingRight;
709 int leftOfCenter = availableWidth / 2;
710 int rightOfCenter = leftOfCenter;
711
712 if (mHomeLayout.getVisibility() != GONE) {
Ed Heyl1c603002010-11-18 12:18:23 -0800713 mHomeLayout.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
714 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
715 final int homeWidth = mHomeLayout.getMeasuredWidth();
716 availableWidth -= homeWidth;
717 leftOfCenter -= homeWidth;
Adam Powell33b97432010-04-20 10:01:14 -0700718 }
Adam Powell96675b12010-06-10 18:58:59 -0700719
Adam Powell9b4bee02011-04-27 19:24:47 -0700720 if (mMenuView != null && mMenuView.getParent() == this) {
Adam Powell96675b12010-06-10 18:58:59 -0700721 availableWidth = measureChildView(mMenuView, availableWidth,
Adam Powell7ade1be2010-06-17 12:51:21 -0700722 childSpecHeight, 0);
Adam Powell9ab97872010-10-26 21:47:29 -0700723 rightOfCenter -= mMenuView.getMeasuredWidth();
Adam Powell33b97432010-04-20 10:01:14 -0700724 }
Adam Powell9ab97872010-10-26 21:47:29 -0700725
Adam Powell2a7ea672011-01-23 20:25:15 -0800726 boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800727 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
728 if (showTitle) {
Adam Powell9ab97872010-10-26 21:47:29 -0700729 availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
730 leftOfCenter -= mTitleLayout.getMeasuredWidth();
731 }
732
Adam Powell33b97432010-04-20 10:01:14 -0700733 switch (mNavigationMode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700734 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800735 if (mListNavLayout != null) {
736 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
737 availableWidth -= itemPaddingSize;
738 leftOfCenter -= itemPaddingSize;
739 mListNavLayout.measure(
Adam Powella7db0372010-06-30 17:08:47 -0700740 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800741 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
742 final int listNavWidth = mListNavLayout.getMeasuredWidth();
743 availableWidth -= listNavWidth;
744 leftOfCenter -= listNavWidth;
Adam Powell33b97432010-04-20 10:01:14 -0700745 }
746 break;
Adam Powell661c9082010-07-02 10:09:44 -0700747 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powell2b6230e2010-09-07 17:55:25 -0700748 if (mTabScrollView != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800749 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
750 availableWidth -= itemPaddingSize;
751 leftOfCenter -= itemPaddingSize;
Adam Powell2b6230e2010-09-07 17:55:25 -0700752 mTabScrollView.measure(
Adam Powell661c9082010-07-02 10:09:44 -0700753 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
Adam Powellca259f42010-09-08 01:21:42 -0700754 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
Adam Powell9ab97872010-10-26 21:47:29 -0700755 final int tabWidth = mTabScrollView.getMeasuredWidth();
756 availableWidth -= tabWidth;
757 leftOfCenter -= tabWidth;
Adam Powell661c9082010-07-02 10:09:44 -0700758 }
759 break;
Adam Powell33b97432010-04-20 10:01:14 -0700760 }
761
Adam Powell6af97e12010-11-11 21:11:53 -0800762 if (mIndeterminateProgressView != null &&
763 mIndeterminateProgressView.getVisibility() != GONE) {
764 availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
765 childSpecHeight, 0);
766 rightOfCenter -= mIndeterminateProgressView.getMeasuredWidth();
767 }
768
Adam Powell9ab97872010-10-26 21:47:29 -0700769 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
770 final LayoutParams lp = generateLayoutParams(mCustomNavView.getLayoutParams());
771 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
772 (ActionBar.LayoutParams) lp : null;
773
774 int horizontalMargin = 0;
775 int verticalMargin = 0;
776 if (ablp != null) {
777 horizontalMargin = ablp.leftMargin + ablp.rightMargin;
778 verticalMargin = ablp.topMargin + ablp.bottomMargin;
779 }
780
781 // If the action bar is wrapping to its content height, don't allow a custom
782 // view to MATCH_PARENT.
783 int customNavHeightMode;
784 if (mContentHeight <= 0) {
785 customNavHeightMode = MeasureSpec.AT_MOST;
786 } else {
787 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
788 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
789 }
790 final int customNavHeight = Math.max(0,
791 (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
792
793 final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
794 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
795 int customNavWidth = Math.max(0,
796 (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
797 - horizontalMargin);
798 final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
799 Gravity.HORIZONTAL_GRAVITY_MASK;
800
801 // Centering a custom view is treated specially; we try to center within the whole
802 // action bar rather than in the available space.
803 if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
804 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
805 }
806
807 mCustomNavView.measure(
808 MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
809 MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
810 }
811
Adam Powelle2194442010-08-12 18:13:03 -0700812 if (mContentHeight <= 0) {
813 int measuredHeight = 0;
814 final int count = getChildCount();
815 for (int i = 0; i < count; i++) {
816 View v = getChildAt(i);
817 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
818 if (paddedViewHeight > measuredHeight) {
819 measuredHeight = paddedViewHeight;
820 }
821 }
822 setMeasuredDimension(contentWidth, measuredHeight);
823 } else {
824 setMeasuredDimension(contentWidth, maxHeight);
825 }
826
827 if (mContextView != null) {
828 mContextView.setHeight(getMeasuredHeight());
829 }
Adam Powell6af97e12010-11-11 21:11:53 -0800830
831 if (mProgressView != null && mProgressView.getVisibility() != GONE) {
832 mProgressView.measure(MeasureSpec.makeMeasureSpec(
833 contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
834 MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
835 }
Adam Powell33b97432010-04-20 10:01:14 -0700836 }
837
Adam Powell33b97432010-04-20 10:01:14 -0700838 @Override
839 protected void onLayout(boolean changed, int l, int t, int r, int b) {
840 int x = getPaddingLeft();
841 final int y = getPaddingTop();
842 final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
843
Adam Powell9ab97872010-10-26 21:47:29 -0700844 if (mHomeLayout.getVisibility() != GONE) {
845 x += positionChild(mHomeLayout, x, y, contentHeight);
Adam Powell33b97432010-04-20 10:01:14 -0700846 }
847
Adam Powell2a7ea672011-01-23 20:25:15 -0800848 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800849 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
850 if (showTitle) {
Adam Powell9ab97872010-10-26 21:47:29 -0700851 x += positionChild(mTitleLayout, x, y, contentHeight);
852 }
853
Adam Powell33b97432010-04-20 10:01:14 -0700854 switch (mNavigationMode) {
Adam Powella4082912010-06-04 18:34:02 -0700855 case ActionBar.NAVIGATION_MODE_STANDARD:
Adam Powell33b97432010-04-20 10:01:14 -0700856 break;
Adam Powell9ab97872010-10-26 21:47:29 -0700857 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800858 if (mListNavLayout != null) {
859 if (showTitle) x += mItemPadding;
860 x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
Adam Powella4082912010-06-04 18:34:02 -0700861 }
862 break;
Adam Powell661c9082010-07-02 10:09:44 -0700863 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powell2b6230e2010-09-07 17:55:25 -0700864 if (mTabScrollView != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800865 if (showTitle) x += mItemPadding;
866 x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
Adam Powell661c9082010-07-02 10:09:44 -0700867 }
Adam Powell6af97e12010-11-11 21:11:53 -0800868 break;
Adam Powell33b97432010-04-20 10:01:14 -0700869 }
870
Adam Powell9ab97872010-10-26 21:47:29 -0700871 int menuLeft = r - l - getPaddingRight();
Adam Powell9b4bee02011-04-27 19:24:47 -0700872 if (mMenuView != null && mMenuView.getParent() == this) {
Adam Powell9ab97872010-10-26 21:47:29 -0700873 positionChildInverse(mMenuView, menuLeft, y, contentHeight);
874 menuLeft -= mMenuView.getMeasuredWidth();
875 }
876
Adam Powell6af97e12010-11-11 21:11:53 -0800877 if (mIndeterminateProgressView != null &&
878 mIndeterminateProgressView.getVisibility() != GONE) {
879 positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight);
880 menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
881 }
882
Adam Powell9ab97872010-10-26 21:47:29 -0700883 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
884 LayoutParams lp = mCustomNavView.getLayoutParams();
885 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
886 (ActionBar.LayoutParams) lp : null;
887
888 final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
889 final int navWidth = mCustomNavView.getMeasuredWidth();
890
891 int topMargin = 0;
892 int bottomMargin = 0;
893 if (ablp != null) {
894 x += ablp.leftMargin;
895 menuLeft -= ablp.rightMargin;
896 topMargin = ablp.topMargin;
897 bottomMargin = ablp.bottomMargin;
898 }
899
900 int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
901 // See if we actually have room to truly center; if not push against left or right.
902 if (hgravity == Gravity.CENTER_HORIZONTAL) {
903 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
904 if (centeredLeft < x) {
905 hgravity = Gravity.LEFT;
906 } else if (centeredLeft + navWidth > menuLeft) {
907 hgravity = Gravity.RIGHT;
908 }
909 }
910
911 int xpos = 0;
912 switch (hgravity) {
913 case Gravity.CENTER_HORIZONTAL:
914 xpos = ((mRight - mLeft) - navWidth) / 2;
915 break;
916 case Gravity.LEFT:
917 xpos = x;
918 break;
919 case Gravity.RIGHT:
920 xpos = menuLeft - navWidth;
921 break;
922 }
923
924 int ypos = 0;
925 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
926 case Gravity.CENTER_VERTICAL:
Jeff Sharkeyf7868052010-11-04 12:42:18 -0700927 final int paddedTop = mTop + getPaddingTop();
928 final int paddedBottom = mBottom - getPaddingBottom();
929 ypos = ((paddedBottom - paddedTop) - mCustomNavView.getMeasuredHeight()) / 2;
Adam Powell9ab97872010-10-26 21:47:29 -0700930 break;
931 case Gravity.TOP:
932 ypos = getPaddingTop() + topMargin;
933 break;
934 case Gravity.BOTTOM:
935 ypos = getHeight() - getPaddingBottom() - mCustomNavView.getMeasuredHeight()
936 - bottomMargin;
937 break;
938 }
939 x += positionChild(mCustomNavView, xpos, ypos, contentHeight);
Adam Powell33b97432010-04-20 10:01:14 -0700940 }
Adam Powell6af97e12010-11-11 21:11:53 -0800941
942 if (mProgressView != null) {
943 mProgressView.bringToFront();
944 final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
945 mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
946 mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
947 }
Adam Powell33b97432010-04-20 10:01:14 -0700948 }
949
Adam Powell661c9082010-07-02 10:09:44 -0700950 private static class TabView extends LinearLayout {
951 private ActionBar.Tab mTab;
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700952 private TextView mTextView;
953 private ImageView mIconView;
954 private View mCustomView;
Adam Powell661c9082010-07-02 10:09:44 -0700955
956 public TabView(Context context, ActionBar.Tab tab) {
Adam Powellca259f42010-09-08 01:21:42 -0700957 super(context, null, com.android.internal.R.attr.actionBarTabStyle);
Adam Powell661c9082010-07-02 10:09:44 -0700958 mTab = tab;
959
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700960 update();
961
962 setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
963 LayoutParams.MATCH_PARENT, 1));
964 }
965
966 public void update() {
967 final ActionBar.Tab tab = mTab;
Adam Powell2b6230e2010-09-07 17:55:25 -0700968 final View custom = tab.getCustomView();
969 if (custom != null) {
970 addView(custom);
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700971 mCustomView = custom;
972 if (mTextView != null) mTextView.setVisibility(GONE);
973 if (mIconView != null) {
974 mIconView.setVisibility(GONE);
975 mIconView.setImageDrawable(null);
976 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700977 } else {
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700978 if (mCustomView != null) {
979 removeView(mCustomView);
980 mCustomView = null;
981 }
Adam Powell661c9082010-07-02 10:09:44 -0700982
Adam Powell2b6230e2010-09-07 17:55:25 -0700983 final Drawable icon = tab.getIcon();
984 final CharSequence text = tab.getText();
Adam Powell661c9082010-07-02 10:09:44 -0700985
Adam Powell2b6230e2010-09-07 17:55:25 -0700986 if (icon != null) {
Adam Powell0d8ec1d2011-05-03 14:49:13 -0700987 if (mIconView == null) {
988 ImageView iconView = new ImageView(getContext());
989 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
990 LayoutParams.WRAP_CONTENT);
991 lp.gravity = Gravity.CENTER_VERTICAL;
992 iconView.setLayoutParams(lp);
993 addView(iconView, 0);
994 mIconView = iconView;
995 }
996 mIconView.setImageDrawable(icon);
997 mIconView.setVisibility(VISIBLE);
998 } else if (mIconView != null) {
999 mIconView.setVisibility(GONE);
1000 mIconView.setImageDrawable(null);
Adam Powell2b6230e2010-09-07 17:55:25 -07001001 }
Adam Powell661c9082010-07-02 10:09:44 -07001002
Adam Powell2b6230e2010-09-07 17:55:25 -07001003 if (text != null) {
Adam Powell0d8ec1d2011-05-03 14:49:13 -07001004 if (mTextView == null) {
1005 TextView textView = new TextView(getContext(), null,
1006 com.android.internal.R.attr.actionBarTabTextStyle);
1007 textView.setSingleLine();
1008 textView.setEllipsize(TruncateAt.END);
1009 LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
1010 LayoutParams.WRAP_CONTENT);
1011 lp.gravity = Gravity.CENTER_VERTICAL;
1012 textView.setLayoutParams(lp);
1013 addView(textView);
1014 mTextView = textView;
1015 }
1016 mTextView.setText(text);
1017 mTextView.setVisibility(VISIBLE);
1018 } else {
1019 mTextView.setVisibility(GONE);
Adam Powell2b6230e2010-09-07 17:55:25 -07001020 }
Adam Powell661c9082010-07-02 10:09:44 -07001021 }
Adam Powell661c9082010-07-02 10:09:44 -07001022 }
1023
1024 public ActionBar.Tab getTab() {
1025 return mTab;
1026 }
1027 }
1028
1029 private class TabClickListener implements OnClickListener {
1030 public void onClick(View view) {
1031 TabView tabView = (TabView) view;
1032 tabView.getTab().select();
1033 final int tabCount = mTabLayout.getChildCount();
1034 for (int i = 0; i < tabCount; i++) {
1035 final View child = mTabLayout.getChildAt(i);
1036 child.setSelected(child == view);
1037 }
1038 }
1039 }
Adam Powell2b0952b2011-03-09 00:15:38 -08001040
1041 private static class HomeView extends FrameLayout {
1042 private View mUpView;
1043 private View mIconView;
1044
1045 public HomeView(Context context) {
1046 this(context, null);
1047 }
1048
1049 public HomeView(Context context, AttributeSet attrs) {
1050 super(context, attrs);
1051 }
1052
1053 @Override
1054 protected void onFinishInflate() {
1055 mUpView = findViewById(com.android.internal.R.id.up);
1056 mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
1057 }
1058
1059 @Override
1060 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1061 measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
1062 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1063 int width = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
1064 int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
1065 measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
1066 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1067 width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
1068 height = Math.max(height,
1069 iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
1070 setMeasuredDimension(width, height);
1071 }
1072
1073 @Override
1074 protected void onLayout(boolean changed, int l, int t, int r, int b) {
1075 final int vCenter = (b - t) / 2;
1076 int width = r - l;
1077 if (mUpView.getVisibility() != GONE) {
1078 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1079 final int upHeight = mUpView.getMeasuredHeight();
1080 final int upWidth = mUpView.getMeasuredWidth();
1081 final int upTop = t + vCenter - upHeight / 2;
1082 mUpView.layout(l, upTop, l + upWidth, upTop + upHeight);
1083 final int upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
1084 width -= upOffset;
1085 l += upOffset;
1086 }
1087 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1088 final int iconHeight = mIconView.getMeasuredHeight();
1089 final int iconWidth = mIconView.getMeasuredWidth();
1090 final int hCenter = (r - l) / 2;
1091 final int iconLeft = l + iconLp.leftMargin + hCenter - iconWidth / 2;
1092 final int iconTop = t + iconLp.topMargin + vCenter - iconHeight / 2;
1093 mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
1094 }
1095 }
Adam Powell33b97432010-04-20 10:01:14 -07001096}