blob: 7da8d4659646f5df51926f1da5a407b327e1e9b7 [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 Powell8d02dea2011-05-31 21:35:13 -070024import com.android.internal.view.menu.MenuItemImpl;
Adam Powell696cba52011-03-29 10:38:16 -070025import com.android.internal.view.menu.MenuPresenter;
Adam Powell8d02dea2011-05-31 21:35:13 -070026import com.android.internal.view.menu.MenuView;
27import com.android.internal.view.menu.SubMenuBuilder;
Adam Powell33b97432010-04-20 10:01:14 -070028
29import android.app.ActionBar;
Adam Powell8515ee82010-11-30 14:09:55 -080030import android.app.ActionBar.OnNavigationListener;
Adam Powell9146ac72010-08-16 18:53:38 -070031import android.app.Activity;
Adam Powell33b97432010-04-20 10:01:14 -070032import android.content.Context;
33import android.content.pm.ApplicationInfo;
34import android.content.pm.PackageManager;
Adam Powell9ab97872010-10-26 21:47:29 -070035import android.content.pm.PackageManager.NameNotFoundException;
Adam Powell45c0b192011-07-28 15:11:57 -070036import android.content.res.Configuration;
Adam Powell33b97432010-04-20 10:01:14 -070037import android.content.res.TypedArray;
Adam Powell6231ab82012-06-22 14:08:11 -070038import android.graphics.Rect;
Adam Powell33b97432010-04-20 10:01:14 -070039import android.graphics.drawable.Drawable;
Adam Powell8d02dea2011-05-31 21:35:13 -070040import android.os.Parcel;
41import android.os.Parcelable;
Adam Powell2a7ea672011-01-23 20:25:15 -080042import android.text.TextUtils;
Adam Powell33b97432010-04-20 10:01:14 -070043import android.util.AttributeSet;
Adam Powell9ab97872010-10-26 21:47:29 -070044import android.util.Log;
Adam Powell038f1c82011-07-21 14:28:10 -070045import android.view.CollapsibleActionView;
Adam Powell661c9082010-07-02 10:09:44 -070046import android.view.Gravity;
Adam Powell89e06452010-06-23 20:24:52 -070047import android.view.LayoutInflater;
48import android.view.Menu;
Adam Powell8d02dea2011-05-31 21:35:13 -070049import android.view.MenuItem;
Adam Powell7bc3ca02011-08-26 18:29:58 -070050import android.view.MotionEvent;
Adam Powell6231ab82012-06-22 14:08:11 -070051import android.view.TouchDelegate;
Adam Powell89e06452010-06-23 20:24:52 -070052import android.view.View;
53import android.view.ViewGroup;
Adam Powell9ab97872010-10-26 21:47:29 -070054import android.view.ViewParent;
Adam Powell8d12e202010-11-15 16:44:17 -080055import android.view.Window;
Adam Powell7bc3ca02011-08-26 18:29:58 -070056import android.view.accessibility.AccessibilityEvent;
Adam Powella4082912010-06-04 18:34:02 -070057import android.widget.AdapterView;
Adam Powell2b0952b2011-03-09 00:15:38 -080058import android.widget.FrameLayout;
Adam Powell33b97432010-04-20 10:01:14 -070059import android.widget.ImageView;
Adam Powell0e94b512010-06-29 17:58:20 -070060import android.widget.LinearLayout;
Adam Powell6af97e12010-11-11 21:11:53 -080061import android.widget.ProgressBar;
Adam Powella4082912010-06-04 18:34:02 -070062import android.widget.Spinner;
63import android.widget.SpinnerAdapter;
Adam Powell33b97432010-04-20 10:01:14 -070064import android.widget.TextView;
65
Adam Powell33b97432010-04-20 10:01:14 -070066/**
67 * @hide
68 */
Adam Powell640a66e2011-04-29 10:18:53 -070069public class ActionBarView extends AbsActionBarView {
Adam Powell33b97432010-04-20 10:01:14 -070070 private static final String TAG = "ActionBarView";
Adam Powellbe4d68e2010-10-08 18:16:34 -070071
Adam Powell33b97432010-04-20 10:01:14 -070072 /**
73 * Display options applied by default
74 */
75 public static final int DISPLAY_DEFAULT = 0;
76
77 /**
78 * Display options that require re-layout as opposed to a simple invalidate
79 */
Adam Powella1700782010-05-13 13:27:35 -070080 private static final int DISPLAY_RELAYOUT_MASK =
Adam Powell9ab97872010-10-26 21:47:29 -070081 ActionBar.DISPLAY_SHOW_HOME |
82 ActionBar.DISPLAY_USE_LOGO |
83 ActionBar.DISPLAY_HOME_AS_UP |
84 ActionBar.DISPLAY_SHOW_CUSTOM |
85 ActionBar.DISPLAY_SHOW_TITLE;
86
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -070087 private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
Adam Powell33b97432010-04-20 10:01:14 -070088
Adam Powell33b97432010-04-20 10:01:14 -070089 private int mNavigationMode;
Adam Powell82f24e82011-08-18 20:15:20 -070090 private int mDisplayOptions = -1;
Adam Powell33b97432010-04-20 10:01:14 -070091 private CharSequence mTitle;
92 private CharSequence mSubtitle;
93 private Drawable mIcon;
94 private Drawable mLogo;
Adam Powell33b97432010-04-20 10:01:14 -070095
Adam Powell8d02dea2011-05-31 21:35:13 -070096 private HomeView mHomeLayout;
97 private HomeView mExpandedHomeLayout;
Adam Powell0e94b512010-06-29 17:58:20 -070098 private LinearLayout mTitleLayout;
Adam Powell33b97432010-04-20 10:01:14 -070099 private TextView mTitleView;
100 private TextView mSubtitleView;
Adam Powell54c7d7e2011-06-17 20:30:13 -0700101 private View mTitleUpView;
102
Adam Powella4082912010-06-04 18:34:02 -0700103 private Spinner mSpinner;
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800104 private LinearLayout mListNavLayout;
Adam Powellf8ac6b72011-05-23 18:14:09 -0700105 private ScrollingTabContainerView mTabScrollView;
Adam Powella4082912010-06-04 18:34:02 -0700106 private View mCustomNavView;
Adam Powell6af97e12010-11-11 21:11:53 -0800107 private ProgressBar mProgressView;
108 private ProgressBar mIndeterminateProgressView;
109
110 private int mProgressBarPadding;
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800111 private int mItemPadding;
Adam Powell33b97432010-04-20 10:01:14 -0700112
Adam Powelle2194442010-08-12 18:13:03 -0700113 private int mTitleStyleRes;
114 private int mSubtitleStyleRes;
Adam Powell6af97e12010-11-11 21:11:53 -0800115 private int mProgressStyle;
116 private int mIndeterminateProgressStyle;
Adam Powelle2194442010-08-12 18:13:03 -0700117
Adam Powelle92ea342010-07-14 14:45:50 -0700118 private boolean mUserTitle;
Adam Powelldae78242011-04-25 15:23:41 -0700119 private boolean mIncludeTabs;
Adam Powelld21aa122011-05-27 13:09:52 -0700120 private boolean mIsCollapsable;
Adam Powellf6ce6a92011-06-29 10:25:01 -0700121 private boolean mIsCollapsed;
Adam Powell33b97432010-04-20 10:01:14 -0700122
Adam Powell96675b12010-06-10 18:58:59 -0700123 private MenuBuilder mOptionsMenu;
Adam Powell96675b12010-06-10 18:58:59 -0700124
Adam Powelle2194442010-08-12 18:13:03 -0700125 private ActionBarContextView mContextView;
126
Adam Powell33b97432010-04-20 10:01:14 -0700127 private ActionMenuItem mLogoNavItem;
Adam Powell9ab97872010-10-26 21:47:29 -0700128
129 private SpinnerAdapter mSpinnerAdapter;
Adam Powell8515ee82010-11-30 14:09:55 -0800130 private OnNavigationListener mCallback;
Adam Powell33b97432010-04-20 10:01:14 -0700131
Adam Powellf8ac6b72011-05-23 18:14:09 -0700132 private Runnable mTabSelector;
133
Adam Powell8d02dea2011-05-31 21:35:13 -0700134 private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
135 View mExpandedActionView;
136
Adam Powell915ce0d2011-09-28 15:52:57 -0700137 Window.Callback mWindowCallback;
138
Adam Powell6231ab82012-06-22 14:08:11 -0700139 private final Rect mTempRect = new Rect();
140 private int mMaxHomeSlop;
141 private static final int MAX_HOME_SLOP = 32; // dp
142
Adam Powella4082912010-06-04 18:34:02 -0700143 private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
144 new AdapterView.OnItemSelectedListener() {
145 public void onItemSelected(AdapterView parent, View view, int position, long id) {
146 if (mCallback != null) {
147 mCallback.onNavigationItemSelected(position, id);
148 }
149 }
150 public void onNothingSelected(AdapterView parent) {
151 // Do nothing
152 }
153 };
154
Adam Powell8d02dea2011-05-31 21:35:13 -0700155 private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() {
156 @Override
157 public void onClick(View v) {
158 final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem;
159 if (item != null) {
160 item.collapseActionView();
161 }
162 }
163 };
Adam Powell2b6230e2010-09-07 17:55:25 -0700164
Adam Powell54c7d7e2011-06-17 20:30:13 -0700165 private final OnClickListener mUpClickListener = new OnClickListener() {
166 public void onClick(View v) {
Adam Powell915ce0d2011-09-28 15:52:57 -0700167 mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
Adam Powell54c7d7e2011-06-17 20:30:13 -0700168 }
169 };
170
Adam Powell33b97432010-04-20 10:01:14 -0700171 public ActionBarView(Context context, AttributeSet attrs) {
172 super(context, attrs);
173
Adam Powell654e4e42011-01-03 16:33:50 -0800174 // Background is always provided by the container.
175 setBackgroundResource(0);
176
Adam Powell45c0b192011-07-28 15:11:57 -0700177 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar,
178 com.android.internal.R.attr.actionBarStyle, 0);
Adam Powell33b97432010-04-20 10:01:14 -0700179
Adam Powell9ab97872010-10-26 21:47:29 -0700180 ApplicationInfo appInfo = context.getApplicationInfo();
Adam Powell33b97432010-04-20 10:01:14 -0700181 PackageManager pm = context.getPackageManager();
Adam Powell661c9082010-07-02 10:09:44 -0700182 mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode,
183 ActionBar.NAVIGATION_MODE_STANDARD);
Adam Powell33b97432010-04-20 10:01:14 -0700184 mTitle = a.getText(R.styleable.ActionBar_title);
185 mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
Adam Powell33b97432010-04-20 10:01:14 -0700186
187 mLogo = a.getDrawable(R.styleable.ActionBar_logo);
188 if (mLogo == null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700189 if (context instanceof Activity) {
190 try {
191 mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
192 } catch (NameNotFoundException e) {
193 Log.e(TAG, "Activity component name not found!", e);
194 }
195 }
196 if (mLogo == null) {
197 mLogo = appInfo.loadLogo(pm);
198 }
Adam Powell33b97432010-04-20 10:01:14 -0700199 }
Adam Powell9ab97872010-10-26 21:47:29 -0700200
Adam Powell33b97432010-04-20 10:01:14 -0700201 mIcon = a.getDrawable(R.styleable.ActionBar_icon);
202 if (mIcon == null) {
Adam Powell9ab97872010-10-26 21:47:29 -0700203 if (context instanceof Activity) {
204 try {
205 mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
206 } catch (NameNotFoundException e) {
207 Log.e(TAG, "Activity component name not found!", e);
208 }
209 }
210 if (mIcon == null) {
211 mIcon = appInfo.loadIcon(pm);
212 }
Adam Powell33b97432010-04-20 10:01:14 -0700213 }
Adam Powell9ab97872010-10-26 21:47:29 -0700214
Ed Heyl1c603002010-11-18 12:18:23 -0800215 final LayoutInflater inflater = LayoutInflater.from(context);
Adam Powell9ab97872010-10-26 21:47:29 -0700216
Ed Heyl1c603002010-11-18 12:18:23 -0800217 final int homeResId = a.getResourceId(
Adam Powellb33be1c2010-11-18 12:11:40 -0800218 com.android.internal.R.styleable.ActionBar_homeLayout,
219 com.android.internal.R.layout.action_bar_home);
Adam Powell9ab97872010-10-26 21:47:29 -0700220
Adam Powell8d02dea2011-05-31 21:35:13 -0700221 mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
Ed Heyl1c603002010-11-18 12:18:23 -0800222
Adam Powell8d02dea2011-05-31 21:35:13 -0700223 mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
224 mExpandedHomeLayout.setUp(true);
225 mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
Adam Powell7bc3ca02011-08-26 18:29:58 -0700226 mExpandedHomeLayout.setContentDescription(getResources().getText(
227 R.string.action_bar_up_description));
Adam Powell33b97432010-04-20 10:01:14 -0700228
Adam Powelle2194442010-08-12 18:13:03 -0700229 mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
230 mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
Adam Powell6af97e12010-11-11 21:11:53 -0800231 mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
232 mIndeterminateProgressStyle = a.getResourceId(
233 R.styleable.ActionBar_indeterminateProgressStyle, 0);
234
235 mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800236 mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
Adam Powelle2194442010-08-12 18:13:03 -0700237
Adam Powell9ab97872010-10-26 21:47:29 -0700238 setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
239
Adam Powell33b97432010-04-20 10:01:14 -0700240 final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
241 if (customNavId != 0) {
Ed Heyl1c603002010-11-18 12:18:23 -0800242 mCustomNavView = (View) inflater.inflate(customNavId, this, false);
Adam Powell9ab97872010-10-26 21:47:29 -0700243 mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
244 setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
Adam Powell33b97432010-04-20 10:01:14 -0700245 }
246
Adam Powelle2194442010-08-12 18:13:03 -0700247 mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
Adam Powellbe4d68e2010-10-08 18:16:34 -0700248
Adam Powell33b97432010-04-20 10:01:14 -0700249 a.recycle();
Adam Powell33b97432010-04-20 10:01:14 -0700250
Ben Komaload199ec2010-11-01 12:24:16 -0700251 mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
Adam Powell54c7d7e2011-06-17 20:30:13 -0700252 mHomeLayout.setOnClickListener(mUpClickListener);
Ben Komaload199ec2010-11-01 12:24:16 -0700253 mHomeLayout.setClickable(true);
254 mHomeLayout.setFocusable(true);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700255
256 if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
257 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
258 }
Adam Powell6231ab82012-06-22 14:08:11 -0700259
260 mMaxHomeSlop =
261 (int) (MAX_HOME_SLOP * context.getResources().getDisplayMetrics().density + 0.5f);
Adam Powell33b97432010-04-20 10:01:14 -0700262 }
Adam Powella7db0372010-06-30 17:08:47 -0700263
Patrick Dubroye0a799a2011-05-04 16:19:22 -0700264 @Override
Adam Powell45c0b192011-07-28 15:11:57 -0700265 protected void onConfigurationChanged(Configuration newConfig) {
266 super.onConfigurationChanged(newConfig);
267
Adam Powell07a047f2011-08-31 10:33:20 -0700268 mTitleView = null;
269 mSubtitleView = null;
270 mTitleUpView = null;
271 if (mTitleLayout != null && mTitleLayout.getParent() == this) {
272 removeView(mTitleLayout);
273 }
274 mTitleLayout = null;
275 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
276 initTitle();
277 }
Adam Powell425689e2011-09-08 18:09:33 -0700278
279 if (mTabScrollView != null && mIncludeTabs) {
280 ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
Adam Powellb8440112011-09-12 19:14:11 -0700281 if (lp != null) {
282 lp.width = LayoutParams.WRAP_CONTENT;
283 lp.height = LayoutParams.MATCH_PARENT;
284 }
Adam Powell425689e2011-09-08 18:09:33 -0700285 mTabScrollView.setAllowCollapse(true);
286 }
Adam Powell45c0b192011-07-28 15:11:57 -0700287 }
288
Adam Powell915ce0d2011-09-28 15:52:57 -0700289 /**
290 * Set the window callback used to invoke menu items; used for dispatching home button presses.
291 * @param cb Window callback to dispatch to
292 */
293 public void setWindowCallback(Window.Callback cb) {
294 mWindowCallback = cb;
295 }
296
Adam Powell45c0b192011-07-28 15:11:57 -0700297 @Override
Adam Powellf8ac6b72011-05-23 18:14:09 -0700298 public void onDetachedFromWindow() {
299 super.onDetachedFromWindow();
300 removeCallbacks(mTabSelector);
Adam Powell97e18362011-10-20 15:37:18 -0700301 if (mActionMenuPresenter != null) {
302 mActionMenuPresenter.hideOverflowMenu();
303 mActionMenuPresenter.hideSubMenus();
304 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700305 }
306
307 @Override
Patrick Dubroye0a799a2011-05-04 16:19:22 -0700308 public boolean shouldDelayChildPressedState() {
309 return false;
310 }
311
Adam Powell6af97e12010-11-11 21:11:53 -0800312 public void initProgress() {
313 mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle);
314 mProgressView.setId(R.id.progress_horizontal);
315 mProgressView.setMax(10000);
Adam Powell45b075d2012-01-09 15:41:40 -0800316 mProgressView.setVisibility(GONE);
Adam Powell6af97e12010-11-11 21:11:53 -0800317 addView(mProgressView);
318 }
319
320 public void initIndeterminateProgress() {
321 mIndeterminateProgressView = new ProgressBar(mContext, null, 0,
322 mIndeterminateProgressStyle);
323 mIndeterminateProgressView.setId(R.id.progress_circular);
Adam Powell45b075d2012-01-09 15:41:40 -0800324 mIndeterminateProgressView.setVisibility(GONE);
Adam Powell6af97e12010-11-11 21:11:53 -0800325 addView(mIndeterminateProgressView);
326 }
327
Adam Powella05aba92011-09-23 14:22:49 -0700328 @Override
Adam Powell9b4bee02011-04-27 19:24:47 -0700329 public void setSplitActionBar(boolean splitActionBar) {
330 if (mSplitActionBar != splitActionBar) {
331 if (mMenuView != null) {
Adam Powell894bf542011-07-22 13:39:08 -0700332 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
333 if (oldParent != null) {
334 oldParent.removeView(mMenuView);
335 }
Adam Powell9b4bee02011-04-27 19:24:47 -0700336 if (splitActionBar) {
Adam Powell9b4bee02011-04-27 19:24:47 -0700337 if (mSplitView != null) {
338 mSplitView.addView(mMenuView);
339 }
Adam Powellf203e0a2012-03-06 17:40:12 -0800340 mMenuView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
Adam Powell9b4bee02011-04-27 19:24:47 -0700341 } else {
342 addView(mMenuView);
Adam Powellf203e0a2012-03-06 17:40:12 -0800343 mMenuView.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
Adam Powell9b4bee02011-04-27 19:24:47 -0700344 }
Adam Powellf203e0a2012-03-06 17:40:12 -0800345 mMenuView.requestLayout();
Adam Powell9b4bee02011-04-27 19:24:47 -0700346 }
Adam Powella05aba92011-09-23 14:22:49 -0700347 if (mSplitView != null) {
348 mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE);
349 }
Adam Powellf203e0a2012-03-06 17:40:12 -0800350
351 if (mActionMenuPresenter != null) {
352 if (!splitActionBar) {
353 mActionMenuPresenter.setExpandedActionViewsExclusive(
354 getResources().getBoolean(
355 com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
356 } else {
357 mActionMenuPresenter.setExpandedActionViewsExclusive(false);
358 // Allow full screen width in split mode.
359 mActionMenuPresenter.setWidthLimit(
360 getContext().getResources().getDisplayMetrics().widthPixels, true);
361 // No limit to the item count; use whatever will fit.
362 mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
363 }
364 }
Adam Powella05aba92011-09-23 14:22:49 -0700365 super.setSplitActionBar(splitActionBar);
Adam Powell9b4bee02011-04-27 19:24:47 -0700366 }
367 }
368
369 public boolean isSplitActionBar() {
370 return mSplitActionBar;
371 }
372
Adam Powelldae78242011-04-25 15:23:41 -0700373 public boolean hasEmbeddedTabs() {
374 return mIncludeTabs;
375 }
376
Adam Powellf8ac6b72011-05-23 18:14:09 -0700377 public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
Adam Powelle0adac02011-06-14 13:46:30 -0700378 if (mTabScrollView != null) {
379 removeView(mTabScrollView);
380 }
Adam Powellf8ac6b72011-05-23 18:14:09 -0700381 mTabScrollView = tabs;
382 mIncludeTabs = tabs != null;
Adam Powellc3076422011-06-01 18:19:04 -0700383 if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
Adam Powell39a8dc42011-05-27 18:44:00 -0700384 addView(mTabScrollView);
Adam Powellf5645cb2011-08-10 22:49:02 -0700385 ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams();
386 lp.width = LayoutParams.WRAP_CONTENT;
387 lp.height = LayoutParams.MATCH_PARENT;
388 tabs.setAllowCollapse(true);
Adam Powell39a8dc42011-05-27 18:44:00 -0700389 }
Adam Powelldae78242011-04-25 15:23:41 -0700390 }
391
Adam Powell8515ee82010-11-30 14:09:55 -0800392 public void setCallback(OnNavigationListener callback) {
Adam Powell96675b12010-06-10 18:58:59 -0700393 mCallback = callback;
Adam Powell33b97432010-04-20 10:01:14 -0700394 }
Adam Powella7db0372010-06-30 17:08:47 -0700395
Adam Powell696cba52011-03-29 10:38:16 -0700396 public void setMenu(Menu menu, MenuPresenter.Callback cb) {
Adam Powellf2d7a5d2011-02-07 18:05:24 -0800397 if (menu == mOptionsMenu) return;
398
Adam Powell696cba52011-03-29 10:38:16 -0700399 if (mOptionsMenu != null) {
Adam Powell8d02dea2011-05-31 21:35:13 -0700400 mOptionsMenu.removeMenuPresenter(mActionMenuPresenter);
401 mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter);
Adam Powell696cba52011-03-29 10:38:16 -0700402 }
403
Adam Powell96675b12010-06-10 18:58:59 -0700404 MenuBuilder builder = (MenuBuilder) menu;
405 mOptionsMenu = builder;
406 if (mMenuView != null) {
Adam Powell894bf542011-07-22 13:39:08 -0700407 final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
408 if (oldParent != null) {
409 oldParent.removeView(mMenuView);
410 }
Adam Powell33b97432010-04-20 10:01:14 -0700411 }
Adam Powell8d02dea2011-05-31 21:35:13 -0700412 if (mActionMenuPresenter == null) {
Adam Powell538e5652011-10-11 13:47:08 -0700413 mActionMenuPresenter = new ActionMenuPresenter(mContext);
Adam Powell8d02dea2011-05-31 21:35:13 -0700414 mActionMenuPresenter.setCallback(cb);
Adam Powell11ed1d62011-07-11 21:19:59 -0700415 mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter);
Adam Powell8d02dea2011-05-31 21:35:13 -0700416 mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
Adam Powell696cba52011-03-29 10:38:16 -0700417 }
Adam Powell35265562011-05-27 15:29:41 -0700418
Adam Powell1ab418a2011-06-09 20:49:49 -0700419 ActionMenuView menuView;
Adam Powell96675b12010-06-10 18:58:59 -0700420 final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
421 LayoutParams.MATCH_PARENT);
Adam Powell9b4bee02011-04-27 19:24:47 -0700422 if (!mSplitActionBar) {
Adam Powellb187cd92011-07-20 14:17:56 -0700423 mActionMenuPresenter.setExpandedActionViewsExclusive(
424 getResources().getBoolean(
425 com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
Adam Powellf35d0492011-08-17 13:56:47 -0700426 configPresenters(builder);
Adam Powell1ab418a2011-06-09 20:49:49 -0700427 menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
Adam Powell894bf542011-07-22 13:39:08 -0700428 final ViewGroup oldParent = (ViewGroup) menuView.getParent();
429 if (oldParent != null && oldParent != this) {
430 oldParent.removeView(menuView);
431 }
Adam Powell1ab418a2011-06-09 20:49:49 -0700432 addView(menuView, layoutParams);
Adam Powell9b4bee02011-04-27 19:24:47 -0700433 } else {
Adam Powellb187cd92011-07-20 14:17:56 -0700434 mActionMenuPresenter.setExpandedActionViewsExclusive(false);
Adam Powell9b4bee02011-04-27 19:24:47 -0700435 // Allow full screen width in split mode.
Adam Powell8d02dea2011-05-31 21:35:13 -0700436 mActionMenuPresenter.setWidthLimit(
Adam Powell640a66e2011-04-29 10:18:53 -0700437 getContext().getResources().getDisplayMetrics().widthPixels, true);
Adam Powell9b4bee02011-04-27 19:24:47 -0700438 // No limit to the item count; use whatever will fit.
Adam Powell8d02dea2011-05-31 21:35:13 -0700439 mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
Adam Powell640a66e2011-04-29 10:18:53 -0700440 // Span the whole width
441 layoutParams.width = LayoutParams.MATCH_PARENT;
Adam Powellf35d0492011-08-17 13:56:47 -0700442 configPresenters(builder);
Adam Powell1ab418a2011-06-09 20:49:49 -0700443 menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
Adam Powell9b4bee02011-04-27 19:24:47 -0700444 if (mSplitView != null) {
Adam Powell894bf542011-07-22 13:39:08 -0700445 final ViewGroup oldParent = (ViewGroup) menuView.getParent();
446 if (oldParent != null && oldParent != mSplitView) {
447 oldParent.removeView(menuView);
448 }
Adam Powell9a5cc282011-08-28 16:18:16 -0700449 menuView.setVisibility(getAnimatedVisibility());
Adam Powell1ab418a2011-06-09 20:49:49 -0700450 mSplitView.addView(menuView, layoutParams);
451 } else {
452 // We'll add this later if we missed it this time.
453 menuView.setLayoutParams(layoutParams);
454 }
Adam Powell9b4bee02011-04-27 19:24:47 -0700455 }
Adam Powell96675b12010-06-10 18:58:59 -0700456 mMenuView = menuView;
Adam Powell33b97432010-04-20 10:01:14 -0700457 }
Adam Powella7db0372010-06-30 17:08:47 -0700458
Adam Powellf35d0492011-08-17 13:56:47 -0700459 private void configPresenters(MenuBuilder builder) {
460 if (builder != null) {
461 builder.addMenuPresenter(mActionMenuPresenter);
462 builder.addMenuPresenter(mExpandedMenuPresenter);
463 } else {
464 mActionMenuPresenter.initForMenu(mContext, null);
465 mExpandedMenuPresenter.initForMenu(mContext, null);
466 mActionMenuPresenter.updateMenuView(true);
467 mExpandedMenuPresenter.updateMenuView(true);
468 }
469 }
470
Adam Powellb80d3322011-07-15 21:33:11 -0700471 public boolean hasExpandedActionView() {
472 return mExpandedMenuPresenter != null &&
473 mExpandedMenuPresenter.mCurrentExpandedItem != null;
474 }
475
476 public void collapseActionView() {
477 final MenuItemImpl item = mExpandedMenuPresenter == null ? null :
478 mExpandedMenuPresenter.mCurrentExpandedItem;
479 if (item != null) {
480 item.collapseActionView();
481 }
482 }
483
Adam Powell33b97432010-04-20 10:01:14 -0700484 public void setCustomNavigationView(View view) {
Adam Powell9ab97872010-10-26 21:47:29 -0700485 final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
486 if (mCustomNavView != null && showCustom) {
487 removeView(mCustomNavView);
488 }
Adam Powella4082912010-06-04 18:34:02 -0700489 mCustomNavView = view;
Adam Powell9ab97872010-10-26 21:47:29 -0700490 if (mCustomNavView != null && showCustom) {
491 addView(mCustomNavView);
Adam Powell33b97432010-04-20 10:01:14 -0700492 }
Adam Powell33b97432010-04-20 10:01:14 -0700493 }
Adam Powella7db0372010-06-30 17:08:47 -0700494
Adam Powell33b97432010-04-20 10:01:14 -0700495 public CharSequence getTitle() {
496 return mTitle;
497 }
Adam Powella7db0372010-06-30 17:08:47 -0700498
Adam Powelle92ea342010-07-14 14:45:50 -0700499 /**
500 * Set the action bar title. This will always replace or override window titles.
501 * @param title Title to set
502 *
503 * @see #setWindowTitle(CharSequence)
504 */
Adam Powell33b97432010-04-20 10:01:14 -0700505 public void setTitle(CharSequence title) {
Adam Powelle92ea342010-07-14 14:45:50 -0700506 mUserTitle = true;
507 setTitleImpl(title);
508 }
509
510 /**
511 * Set the window title. A window title will always be replaced or overridden by a user title.
512 * @param title Title to set
513 *
514 * @see #setTitle(CharSequence)
515 */
516 public void setWindowTitle(CharSequence title) {
517 if (!mUserTitle) {
518 setTitleImpl(title);
519 }
520 }
521
522 private void setTitleImpl(CharSequence title) {
Adam Powell33b97432010-04-20 10:01:14 -0700523 mTitle = title;
524 if (mTitleView != null) {
525 mTitleView.setText(title);
Adam Powellb0e217e2011-08-12 11:36:51 -0700526 final boolean visible = mExpandedActionView == null &&
Adam Powell71f34172011-08-11 20:07:11 -0700527 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 &&
Adam Powellb0e217e2011-08-12 11:36:51 -0700528 (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
529 mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
Adam Powell33b97432010-04-20 10:01:14 -0700530 }
531 if (mLogoNavItem != null) {
532 mLogoNavItem.setTitle(title);
533 }
534 }
Adam Powella7db0372010-06-30 17:08:47 -0700535
Adam Powell33b97432010-04-20 10:01:14 -0700536 public CharSequence getSubtitle() {
537 return mSubtitle;
538 }
Adam Powella7db0372010-06-30 17:08:47 -0700539
Adam Powell33b97432010-04-20 10:01:14 -0700540 public void setSubtitle(CharSequence subtitle) {
541 mSubtitle = subtitle;
542 if (mSubtitleView != null) {
543 mSubtitleView.setText(subtitle);
Adam Powell04587962010-11-11 22:15:07 -0800544 mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
Adam Powellb0e217e2011-08-12 11:36:51 -0700545 final boolean visible = mExpandedActionView == null &&
Adam Powell71f34172011-08-11 20:07:11 -0700546 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 &&
Adam Powellb0e217e2011-08-12 11:36:51 -0700547 (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle));
548 mTitleLayout.setVisibility(visible ? VISIBLE : GONE);
Adam Powell33b97432010-04-20 10:01:14 -0700549 }
550 }
Adam Powella7db0372010-06-30 17:08:47 -0700551
Adam Powellc29f4e52011-07-13 20:40:52 -0700552 public void setHomeButtonEnabled(boolean enable) {
553 mHomeLayout.setEnabled(enable);
Adam Powell24340af2011-10-31 22:07:44 -0700554 mHomeLayout.setFocusable(enable);
Adam Powellc29f4e52011-07-13 20:40:52 -0700555 // Make sure the home button has an accurate content description for accessibility.
556 if (!enable) {
557 mHomeLayout.setContentDescription(null);
558 } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
559 mHomeLayout.setContentDescription(mContext.getResources().getText(
560 R.string.action_bar_up_description));
561 } else {
562 mHomeLayout.setContentDescription(mContext.getResources().getText(
563 R.string.action_bar_home_description));
564 }
565 }
566
Adam Powell33b97432010-04-20 10:01:14 -0700567 public void setDisplayOptions(int options) {
Adam Powell82f24e82011-08-18 20:15:20 -0700568 final int flagsChanged = mDisplayOptions == -1 ? -1 : options ^ mDisplayOptions;
Adam Powell33b97432010-04-20 10:01:14 -0700569 mDisplayOptions = options;
Adam Powelldae78242011-04-25 15:23:41 -0700570
Adam Powell33b97432010-04-20 10:01:14 -0700571 if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
Adam Powell54c7d7e2011-06-17 20:30:13 -0700572 final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
Adam Powella8743f12011-11-11 18:35:53 -0800573 final int vis = showHome && mExpandedActionView == null ? VISIBLE : GONE;
Adam Powell9ab97872010-10-26 21:47:29 -0700574 mHomeLayout.setVisibility(vis);
575
576 if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
Adam Powellc29f4e52011-07-13 20:40:52 -0700577 final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
578 mHomeLayout.setUp(setUp);
579
580 // Showing home as up implicitly enables interaction with it.
581 // In honeycomb it was always enabled, so make this transition
582 // a bit easier for developers in the common case.
583 // (It would be silly to show it as up without responding to it.)
584 if (setUp) {
585 setHomeButtonEnabled(true);
586 }
Adam Powella1700782010-05-13 13:27:35 -0700587 }
Adam Powell9ab97872010-10-26 21:47:29 -0700588
Ed Heyl1c603002010-11-18 12:18:23 -0800589 if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
590 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
Adam Powell8d02dea2011-05-31 21:35:13 -0700591 mHomeLayout.setIcon(logoVis ? mLogo : mIcon);
Adam Powell9ab97872010-10-26 21:47:29 -0700592 }
593
594 if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
595 if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
596 initTitle();
597 } else {
598 removeView(mTitleLayout);
599 }
600 }
601
Adam Powell15a16a82011-06-20 10:35:27 -0700602 if (mTitleLayout != null && (flagsChanged &
Adam Powell54c7d7e2011-06-17 20:30:13 -0700603 (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
Adam Powellb1e2f252011-08-22 17:42:12 -0700604 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
605 mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
606 mTitleLayout.setEnabled(!showHome && homeAsUp);
Adam Powell6231ab82012-06-22 14:08:11 -0700607 mTitleLayout.setClickable(!showHome && homeAsUp);
Adam Powell54c7d7e2011-06-17 20:30:13 -0700608 }
609
Adam Powell9ab97872010-10-26 21:47:29 -0700610 if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
611 if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
612 addView(mCustomNavView);
613 } else {
614 removeView(mCustomNavView);
615 }
Adam Powella1700782010-05-13 13:27:35 -0700616 }
617
Adam Powell33b97432010-04-20 10:01:14 -0700618 requestLayout();
619 } else {
620 invalidate();
621 }
Adam Powellf3cd1d92011-04-26 17:31:52 -0700622
623 // Make sure the home button has an accurate content description for accessibility.
Adam Powellc29f4e52011-07-13 20:40:52 -0700624 if (!mHomeLayout.isEnabled()) {
Adam Powellf3cd1d92011-04-26 17:31:52 -0700625 mHomeLayout.setContentDescription(null);
626 } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
627 mHomeLayout.setContentDescription(mContext.getResources().getText(
628 R.string.action_bar_up_description));
629 } else {
630 mHomeLayout.setContentDescription(mContext.getResources().getText(
631 R.string.action_bar_home_description));
632 }
Adam Powell33b97432010-04-20 10:01:14 -0700633 }
634
Adam Powell1969b872011-03-22 11:52:48 -0700635 public void setIcon(Drawable icon) {
636 mIcon = icon;
637 if (icon != null &&
638 ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) {
Adam Powell8d02dea2011-05-31 21:35:13 -0700639 mHomeLayout.setIcon(icon);
Adam Powell1969b872011-03-22 11:52:48 -0700640 }
Adam Powellf8218192012-02-21 17:10:10 -0800641 if (mExpandedActionView != null) {
642 mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources()));
643 }
Adam Powell1969b872011-03-22 11:52:48 -0700644 }
645
Adam Powell45c515b2011-04-21 18:50:20 -0700646 public void setIcon(int resId) {
Adam Powellf2b09612011-08-12 14:18:04 -0700647 setIcon(mContext.getResources().getDrawable(resId));
Adam Powell45c515b2011-04-21 18:50:20 -0700648 }
649
Adam Powell1969b872011-03-22 11:52:48 -0700650 public void setLogo(Drawable logo) {
651 mLogo = logo;
652 if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
Adam Powell8d02dea2011-05-31 21:35:13 -0700653 mHomeLayout.setIcon(logo);
Adam Powell1969b872011-03-22 11:52:48 -0700654 }
655 }
656
Adam Powell45c515b2011-04-21 18:50:20 -0700657 public void setLogo(int resId) {
Adam Powell29764ea2011-08-04 13:12:01 -0700658 setLogo(mContext.getResources().getDrawable(resId));
Adam Powell45c515b2011-04-21 18:50:20 -0700659 }
660
Adam Powell33b97432010-04-20 10:01:14 -0700661 public void setNavigationMode(int mode) {
Adam Powella1700782010-05-13 13:27:35 -0700662 final int oldMode = mNavigationMode;
663 if (mode != oldMode) {
664 switch (oldMode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700665 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powellc3076422011-06-01 18:19:04 -0700666 if (mListNavLayout != null) {
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800667 removeView(mListNavLayout);
Adam Powella4082912010-06-04 18:34:02 -0700668 }
669 break;
Adam Powell661c9082010-07-02 10:09:44 -0700670 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powellf8ac6b72011-05-23 18:14:09 -0700671 if (mTabScrollView != null && mIncludeTabs) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700672 removeView(mTabScrollView);
Adam Powell661c9082010-07-02 10:09:44 -0700673 }
Adam Powella1700782010-05-13 13:27:35 -0700674 }
675
676 switch (mode) {
Adam Powell9ab97872010-10-26 21:47:29 -0700677 case ActionBar.NAVIGATION_MODE_LIST:
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800678 if (mSpinner == null) {
679 mSpinner = new Spinner(mContext, null,
680 com.android.internal.R.attr.actionDropDownStyle);
681 mListNavLayout = new LinearLayout(mContext, null,
682 com.android.internal.R.attr.actionBarTabBarStyle);
683 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
Adam Powelle7d46842011-01-13 21:36:09 -0800684 LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800685 params.gravity = Gravity.CENTER;
686 mListNavLayout.addView(mSpinner, params);
687 }
688 if (mSpinner.getAdapter() != mSpinnerAdapter) {
689 mSpinner.setAdapter(mSpinnerAdapter);
690 }
Adam Powella4082912010-06-04 18:34:02 -0700691 mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
Adam Powell3f7f7ac2010-12-05 16:44:38 -0800692 addView(mListNavLayout);
Adam Powella4082912010-06-04 18:34:02 -0700693 break;
Adam Powell661c9082010-07-02 10:09:44 -0700694 case ActionBar.NAVIGATION_MODE_TABS:
Adam Powellf8ac6b72011-05-23 18:14:09 -0700695 if (mTabScrollView != null && mIncludeTabs) {
Adam Powelldae78242011-04-25 15:23:41 -0700696 addView(mTabScrollView);
697 }
Adam Powell661c9082010-07-02 10:09:44 -0700698 break;
Adam Powella1700782010-05-13 13:27:35 -0700699 }
Adam Powell33b97432010-04-20 10:01:14 -0700700 mNavigationMode = mode;
701 requestLayout();
702 }
703 }
Adam Powelldae78242011-04-25 15:23:41 -0700704
Adam Powella4082912010-06-04 18:34:02 -0700705 public void setDropdownAdapter(SpinnerAdapter adapter) {
Adam Powell9ab97872010-10-26 21:47:29 -0700706 mSpinnerAdapter = adapter;
707 if (mSpinner != null) {
708 mSpinner.setAdapter(adapter);
709 }
710 }
711
712 public SpinnerAdapter getDropdownAdapter() {
713 return mSpinnerAdapter;
Adam Powella4082912010-06-04 18:34:02 -0700714 }
Adam Powell17809772010-07-21 13:25:11 -0700715
716 public void setDropdownSelectedPosition(int position) {
717 mSpinner.setSelection(position);
718 }
719
720 public int getDropdownSelectedPosition() {
721 return mSpinner.getSelectedItemPosition();
722 }
723
Adam Powell33b97432010-04-20 10:01:14 -0700724 public View getCustomNavigationView() {
Adam Powella4082912010-06-04 18:34:02 -0700725 return mCustomNavView;
Adam Powell33b97432010-04-20 10:01:14 -0700726 }
727
728 public int getNavigationMode() {
729 return mNavigationMode;
730 }
731
732 public int getDisplayOptions() {
733 return mDisplayOptions;
734 }
Adam Powella7db0372010-06-30 17:08:47 -0700735
736 @Override
Adam Powell9a5cc282011-08-28 16:18:16 -0700737 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
Adam Powella7db0372010-06-30 17:08:47 -0700738 // Used by custom nav views if they don't supply layout params. Everything else
739 // added to an ActionBarView should have them already.
Adam Powell9ab97872010-10-26 21:47:29 -0700740 return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
Adam Powella7db0372010-06-30 17:08:47 -0700741 }
742
Adam Powell33b97432010-04-20 10:01:14 -0700743 @Override
744 protected void onFinishInflate() {
745 super.onFinishInflate();
746
Adam Powell9ab97872010-10-26 21:47:29 -0700747 addView(mHomeLayout);
748
Adam Powell9ab97872010-10-26 21:47:29 -0700749 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
750 final ViewParent parent = mCustomNavView.getParent();
751 if (parent != this) {
752 if (parent instanceof ViewGroup) {
753 ((ViewGroup) parent).removeView(mCustomNavView);
754 }
Adam Powella4082912010-06-04 18:34:02 -0700755 addView(mCustomNavView);
Adam Powell33b97432010-04-20 10:01:14 -0700756 }
Adam Powell33b97432010-04-20 10:01:14 -0700757 }
758 }
Adam Powellc8b0b002011-06-23 14:39:05 -0700759
Adam Powella1700782010-05-13 13:27:35 -0700760 private void initTitle() {
Adam Powell15a16a82011-06-20 10:35:27 -0700761 if (mTitleLayout == null) {
762 LayoutInflater inflater = LayoutInflater.from(getContext());
Adam Powell9e58df52011-08-15 17:06:49 -0700763 mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item,
764 this, false);
Adam Powell15a16a82011-06-20 10:35:27 -0700765 mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
766 mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
767 mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
Adam Powell54c7d7e2011-06-17 20:30:13 -0700768
Adam Powell15a16a82011-06-20 10:35:27 -0700769 mTitleLayout.setOnClickListener(mUpClickListener);
Adam Powelle2194442010-08-12 18:13:03 -0700770
Adam Powell15a16a82011-06-20 10:35:27 -0700771 if (mTitleStyleRes != 0) {
772 mTitleView.setTextAppearance(mContext, mTitleStyleRes);
773 }
774 if (mTitle != null) {
775 mTitleView.setText(mTitle);
776 }
Adam Powelle2194442010-08-12 18:13:03 -0700777
Adam Powell15a16a82011-06-20 10:35:27 -0700778 if (mSubtitleStyleRes != 0) {
779 mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
780 }
781 if (mSubtitle != null) {
782 mSubtitleView.setText(mSubtitle);
783 mSubtitleView.setVisibility(VISIBLE);
784 }
785
786 final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
Adam Powellb1e2f252011-08-22 17:42:12 -0700787 final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
Adam Powell6231ab82012-06-22 14:08:11 -0700788 final boolean showTitleUp = !showHome;
789 mTitleUpView.setVisibility(showTitleUp ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
790 mTitleLayout.setEnabled(homeAsUp && showTitleUp);
791 mTitleLayout.setClickable(homeAsUp && showTitleUp);
Adam Powell0e94b512010-06-29 17:58:20 -0700792 }
Adam Powelle2194442010-08-12 18:13:03 -0700793
Adam Powell9e58df52011-08-15 17:06:49 -0700794 addView(mTitleLayout);
Adam Powell82f24e82011-08-18 20:15:20 -0700795 if (mExpandedActionView != null ||
796 (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
797 // Don't show while in expanded mode or with empty text
Adam Powell71f34172011-08-11 20:07:11 -0700798 mTitleLayout.setVisibility(GONE);
799 }
Adam Powella1700782010-05-13 13:27:35 -0700800 }
Adam Powell33b97432010-04-20 10:01:14 -0700801
Adam Powelle2194442010-08-12 18:13:03 -0700802 public void setContextView(ActionBarContextView view) {
803 mContextView = view;
804 }
805
Adam Powelld21aa122011-05-27 13:09:52 -0700806 public void setCollapsable(boolean collapsable) {
807 mIsCollapsable = collapsable;
808 }
809
Adam Powellf6ce6a92011-06-29 10:25:01 -0700810 public boolean isCollapsed() {
811 return mIsCollapsed;
812 }
813
Adam Powell33b97432010-04-20 10:01:14 -0700814 @Override
815 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Adam Powelld21aa122011-05-27 13:09:52 -0700816 final int childCount = getChildCount();
817 if (mIsCollapsable) {
818 int visibleChildren = 0;
819 for (int i = 0; i < childCount; i++) {
820 final View child = getChildAt(i);
821 if (child.getVisibility() != GONE &&
822 !(child == mMenuView && mMenuView.getChildCount() == 0)) {
823 visibleChildren++;
824 }
825 }
826
827 if (visibleChildren == 0) {
828 // No size for an empty action bar when collapsable.
829 setMeasuredDimension(0, 0);
Adam Powellf6ce6a92011-06-29 10:25:01 -0700830 mIsCollapsed = true;
Adam Powelld21aa122011-05-27 13:09:52 -0700831 return;
832 }
833 }
Adam Powellf6ce6a92011-06-29 10:25:01 -0700834 mIsCollapsed = false;
Adam Powelld21aa122011-05-27 13:09:52 -0700835
Adam Powell33b97432010-04-20 10:01:14 -0700836 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
837 if (widthMode != MeasureSpec.EXACTLY) {
838 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
839 "with android:layout_width=\"match_parent\" (or fill_parent)");
840 }
841
842 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
843 if (heightMode != MeasureSpec.AT_MOST) {
844 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
845 "with android:layout_height=\"wrap_content\"");
846 }
847
848 int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
Adam Powelle2194442010-08-12 18:13:03 -0700849
850 int maxHeight = mContentHeight > 0 ?
851 mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
Adam Powell33b97432010-04-20 10:01:14 -0700852
Adam Powelle2194442010-08-12 18:13:03 -0700853 final int verticalPadding = getPaddingTop() + getPaddingBottom();
Adam Powell9ab97872010-10-26 21:47:29 -0700854 final int paddingLeft = getPaddingLeft();
855 final int paddingRight = getPaddingRight();
Adam Powelle2194442010-08-12 18:13:03 -0700856 final int height = maxHeight - verticalPadding;
Adam Powella1700782010-05-13 13:27:35 -0700857 final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
Adam Powell33b97432010-04-20 10:01:14 -0700858
Adam Powell9ab97872010-10-26 21:47:29 -0700859 int availableWidth = contentWidth - paddingLeft - paddingRight;
860 int leftOfCenter = availableWidth / 2;
861 int rightOfCenter = leftOfCenter;
862
Adam Powellb1e2f252011-08-22 17:42:12 -0700863 HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
Adam Powell8d02dea2011-05-31 21:35:13 -0700864
865 if (homeLayout.getVisibility() != GONE) {
Adam Powell9a5cc282011-08-28 16:18:16 -0700866 final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
Adam Powell0d5d1b7e2011-06-22 17:40:40 -0700867 int homeWidthSpec;
868 if (lp.width < 0) {
869 homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
870 } else {
871 homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
872 }
873 homeLayout.measure(homeWidthSpec,
Ed Heyl1c603002010-11-18 12:18:23 -0800874 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -0700875 final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
Adam Powell1b4a1622011-05-17 12:13:13 -0700876 availableWidth = Math.max(0, availableWidth - homeWidth);
877 leftOfCenter = Math.max(0, availableWidth - homeWidth);
Adam Powell33b97432010-04-20 10:01:14 -0700878 }
Adam Powell96675b12010-06-10 18:58:59 -0700879
Adam Powell9b4bee02011-04-27 19:24:47 -0700880 if (mMenuView != null && mMenuView.getParent() == this) {
Adam Powell96675b12010-06-10 18:58:59 -0700881 availableWidth = measureChildView(mMenuView, availableWidth,
Adam Powell7ade1be2010-06-17 12:51:21 -0700882 childSpecHeight, 0);
Adam Powell1b4a1622011-05-17 12:13:13 -0700883 rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
Adam Powell33b97432010-04-20 10:01:14 -0700884 }
Adam Powell9ab97872010-10-26 21:47:29 -0700885
Adam Powellaa8e509b2011-08-25 09:29:21 -0700886 if (mIndeterminateProgressView != null &&
887 mIndeterminateProgressView.getVisibility() != GONE) {
888 availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
889 childSpecHeight, 0);
890 rightOfCenter = Math.max(0,
891 rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
892 }
Adam Powell9ab97872010-10-26 21:47:29 -0700893
Adam Powellaa8e509b2011-08-25 09:29:21 -0700894 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
895 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
896
897 if (mExpandedActionView == null) {
Adam Powell8d02dea2011-05-31 21:35:13 -0700898 switch (mNavigationMode) {
899 case ActionBar.NAVIGATION_MODE_LIST:
900 if (mListNavLayout != null) {
901 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
902 availableWidth = Math.max(0, availableWidth - itemPaddingSize);
903 leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
904 mListNavLayout.measure(
905 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
906 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
907 final int listNavWidth = mListNavLayout.getMeasuredWidth();
908 availableWidth = Math.max(0, availableWidth - listNavWidth);
909 leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
910 }
911 break;
912 case ActionBar.NAVIGATION_MODE_TABS:
913 if (mTabScrollView != null) {
914 final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
915 availableWidth = Math.max(0, availableWidth - itemPaddingSize);
916 leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
917 mTabScrollView.measure(
918 MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
919 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
920 final int tabWidth = mTabScrollView.getMeasuredWidth();
921 availableWidth = Math.max(0, availableWidth - tabWidth);
922 leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
923 }
924 break;
Adam Powell33b97432010-04-20 10:01:14 -0700925 }
Adam Powell33b97432010-04-20 10:01:14 -0700926 }
927
Adam Powell8d02dea2011-05-31 21:35:13 -0700928 View customView = null;
929 if (mExpandedActionView != null) {
930 customView = mExpandedActionView;
931 } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
932 mCustomNavView != null) {
933 customView = mCustomNavView;
934 }
935
936 if (customView != null) {
Adam Powell9a5cc282011-08-28 16:18:16 -0700937 final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams());
Adam Powell9ab97872010-10-26 21:47:29 -0700938 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
939 (ActionBar.LayoutParams) lp : null;
940
941 int horizontalMargin = 0;
942 int verticalMargin = 0;
943 if (ablp != null) {
944 horizontalMargin = ablp.leftMargin + ablp.rightMargin;
945 verticalMargin = ablp.topMargin + ablp.bottomMargin;
946 }
947
948 // If the action bar is wrapping to its content height, don't allow a custom
949 // view to MATCH_PARENT.
950 int customNavHeightMode;
951 if (mContentHeight <= 0) {
952 customNavHeightMode = MeasureSpec.AT_MOST;
953 } else {
954 customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
955 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
956 }
957 final int customNavHeight = Math.max(0,
958 (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
959
960 final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
961 MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
962 int customNavWidth = Math.max(0,
963 (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
964 - horizontalMargin);
965 final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
966 Gravity.HORIZONTAL_GRAVITY_MASK;
967
968 // Centering a custom view is treated specially; we try to center within the whole
969 // action bar rather than in the available space.
970 if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
971 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
972 }
973
Adam Powell8d02dea2011-05-31 21:35:13 -0700974 customView.measure(
Adam Powell9ab97872010-10-26 21:47:29 -0700975 MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
976 MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
Adam Powellaa8e509b2011-08-25 09:29:21 -0700977 availableWidth -= horizontalMargin + customView.getMeasuredWidth();
978 }
979
980 if (mExpandedActionView == null && showTitle) {
981 availableWidth = measureChildView(mTitleLayout, availableWidth,
982 MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
983 leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
Adam Powell9ab97872010-10-26 21:47:29 -0700984 }
985
Adam Powelle2194442010-08-12 18:13:03 -0700986 if (mContentHeight <= 0) {
987 int measuredHeight = 0;
Adam Powelld21aa122011-05-27 13:09:52 -0700988 for (int i = 0; i < childCount; i++) {
Adam Powelle2194442010-08-12 18:13:03 -0700989 View v = getChildAt(i);
990 int paddedViewHeight = v.getMeasuredHeight() + verticalPadding;
991 if (paddedViewHeight > measuredHeight) {
992 measuredHeight = paddedViewHeight;
993 }
994 }
995 setMeasuredDimension(contentWidth, measuredHeight);
996 } else {
997 setMeasuredDimension(contentWidth, maxHeight);
998 }
999
1000 if (mContextView != null) {
Adam Powell425689e2011-09-08 18:09:33 -07001001 mContextView.setContentHeight(getMeasuredHeight());
Adam Powelle2194442010-08-12 18:13:03 -07001002 }
Adam Powell6af97e12010-11-11 21:11:53 -08001003
1004 if (mProgressView != null && mProgressView.getVisibility() != GONE) {
1005 mProgressView.measure(MeasureSpec.makeMeasureSpec(
1006 contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY),
1007 MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST));
1008 }
Adam Powell33b97432010-04-20 10:01:14 -07001009 }
1010
Adam Powell33b97432010-04-20 10:01:14 -07001011 @Override
1012 protected void onLayout(boolean changed, int l, int t, int r, int b) {
Adam Powell33b97432010-04-20 10:01:14 -07001013 final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
1014
Adam Powelld21aa122011-05-27 13:09:52 -07001015 if (contentHeight <= 0) {
1016 // Nothing to do if we can't see anything.
1017 return;
1018 }
1019
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001020 final boolean isLayoutRtl = isLayoutRtl();
1021 final int direction = isLayoutRtl ? +1 : -1;
1022 int menuStart = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
1023 // In LTR mode, we start from left padding and go to the right; in RTL mode, we start
1024 // from the padding right and go to the left (in reverse way)
1025 int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
1026 final int y = getPaddingTop();
1027
Adam Powellb1e2f252011-08-22 17:42:12 -07001028 HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
Adam Powell6231ab82012-06-22 14:08:11 -07001029 boolean needsTouchDelegate = false;
1030 int homeSlop = mMaxHomeSlop;
1031 int homeRight = 0;
Adam Powell8d02dea2011-05-31 21:35:13 -07001032 if (homeLayout.getVisibility() != GONE) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001033 final int startOffset = homeLayout.getStartOffset();
1034 x += positionChild(homeLayout,
1035 next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
1036 x = next(x, startOffset, isLayoutRtl);
Adam Powell6231ab82012-06-22 14:08:11 -07001037 needsTouchDelegate = homeLayout == mHomeLayout;
1038 homeRight = x;
Adam Powell9ab97872010-10-26 21:47:29 -07001039 }
1040
Adam Powell8d02dea2011-05-31 21:35:13 -07001041 if (mExpandedActionView == null) {
1042 final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
Adam Powell15a16a82011-06-20 10:35:27 -07001043 (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
Adam Powell8d02dea2011-05-31 21:35:13 -07001044 if (showTitle) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001045 x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
Adam Powella4082912010-06-04 18:34:02 -07001046 }
Adam Powell8d02dea2011-05-31 21:35:13 -07001047
1048 switch (mNavigationMode) {
1049 case ActionBar.NAVIGATION_MODE_STANDARD:
1050 break;
1051 case ActionBar.NAVIGATION_MODE_LIST:
1052 if (mListNavLayout != null) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001053 if (showTitle) {
1054 x = next(x, mItemPadding, isLayoutRtl);
1055 }
Adam Powell6231ab82012-06-22 14:08:11 -07001056 homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001057 x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
1058 x = next(x, mItemPadding, isLayoutRtl);
Adam Powell8d02dea2011-05-31 21:35:13 -07001059 }
1060 break;
1061 case ActionBar.NAVIGATION_MODE_TABS:
1062 if (mTabScrollView != null) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001063 if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
Adam Powell6231ab82012-06-22 14:08:11 -07001064 homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001065 x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
1066 x = next(x, mItemPadding, isLayoutRtl);
Adam Powell8d02dea2011-05-31 21:35:13 -07001067 }
1068 break;
Adam Powell661c9082010-07-02 10:09:44 -07001069 }
Adam Powell33b97432010-04-20 10:01:14 -07001070 }
1071
Adam Powell9b4bee02011-04-27 19:24:47 -07001072 if (mMenuView != null && mMenuView.getParent() == this) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001073 positionChild(mMenuView, menuStart, y, contentHeight, !isLayoutRtl);
1074 menuStart += direction * mMenuView.getMeasuredWidth();
Adam Powell9ab97872010-10-26 21:47:29 -07001075 }
1076
Adam Powell6af97e12010-11-11 21:11:53 -08001077 if (mIndeterminateProgressView != null &&
1078 mIndeterminateProgressView.getVisibility() != GONE) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001079 positionChild(mIndeterminateProgressView, menuStart, y, contentHeight, !isLayoutRtl);
1080 menuStart += direction * mIndeterminateProgressView.getMeasuredWidth();
Adam Powell6af97e12010-11-11 21:11:53 -08001081 }
1082
Adam Powell8d02dea2011-05-31 21:35:13 -07001083 View customView = null;
1084 if (mExpandedActionView != null) {
1085 customView = mExpandedActionView;
1086 } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
1087 mCustomNavView != null) {
1088 customView = mCustomNavView;
1089 }
1090 if (customView != null) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001091 final int resolvedLayoutDirection = getResolvedLayoutDirection();
Adam Powell9a5cc282011-08-28 16:18:16 -07001092 ViewGroup.LayoutParams lp = customView.getLayoutParams();
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001093 lp.onResolveLayoutDirection(resolvedLayoutDirection);
Adam Powell9ab97872010-10-26 21:47:29 -07001094 final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
1095 (ActionBar.LayoutParams) lp : null;
Adam Powell9ab97872010-10-26 21:47:29 -07001096 final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
Adam Powell8d02dea2011-05-31 21:35:13 -07001097 final int navWidth = customView.getMeasuredWidth();
Adam Powell9ab97872010-10-26 21:47:29 -07001098
1099 int topMargin = 0;
1100 int bottomMargin = 0;
1101 if (ablp != null) {
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001102 x = next(x, ablp.getMarginStart(), isLayoutRtl);
1103 menuStart += direction * ablp.getMarginEnd();
Adam Powell9ab97872010-10-26 21:47:29 -07001104 topMargin = ablp.topMargin;
1105 bottomMargin = ablp.bottomMargin;
1106 }
1107
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001108 int hgravity = gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
Adam Powell9ab97872010-10-26 21:47:29 -07001109 // See if we actually have room to truly center; if not push against left or right.
1110 if (hgravity == Gravity.CENTER_HORIZONTAL) {
1111 final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001112 if (isLayoutRtl) {
1113 final int centeredStart = centeredLeft + navWidth;
1114 final int centeredEnd = centeredLeft;
1115 if (centeredStart > x) {
1116 hgravity = Gravity.RIGHT;
1117 } else if (centeredEnd < menuStart) {
1118 hgravity = Gravity.LEFT;
1119 }
1120 } else {
1121 final int centeredStart = centeredLeft;
1122 final int centeredEnd = centeredLeft + navWidth;
1123 if (centeredStart < x) {
1124 hgravity = Gravity.LEFT;
1125 } else if (centeredEnd > menuStart) {
1126 hgravity = Gravity.RIGHT;
1127 }
Adam Powell9ab97872010-10-26 21:47:29 -07001128 }
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001129 } else if (gravity == Gravity.NO_GRAVITY) {
1130 hgravity = Gravity.START;
Adam Powell9ab97872010-10-26 21:47:29 -07001131 }
1132
1133 int xpos = 0;
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001134 switch (Gravity.getAbsoluteGravity(hgravity, resolvedLayoutDirection)) {
Adam Powell9ab97872010-10-26 21:47:29 -07001135 case Gravity.CENTER_HORIZONTAL:
1136 xpos = ((mRight - mLeft) - navWidth) / 2;
1137 break;
1138 case Gravity.LEFT:
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001139 xpos = isLayoutRtl ? menuStart : x;
Adam Powell9ab97872010-10-26 21:47:29 -07001140 break;
1141 case Gravity.RIGHT:
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001142 xpos = isLayoutRtl ? x - navWidth : menuStart - navWidth;
Adam Powell9ab97872010-10-26 21:47:29 -07001143 break;
1144 }
1145
Adam Powell7a2424d2011-08-18 11:59:11 -07001146 int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
1147
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001148 if (gravity == Gravity.NO_GRAVITY) {
Adam Powell7a2424d2011-08-18 11:59:11 -07001149 vgravity = Gravity.CENTER_VERTICAL;
1150 }
1151
Adam Powell9ab97872010-10-26 21:47:29 -07001152 int ypos = 0;
Adam Powell7a2424d2011-08-18 11:59:11 -07001153 switch (vgravity) {
Adam Powell9ab97872010-10-26 21:47:29 -07001154 case Gravity.CENTER_VERTICAL:
Adam Powell6556c072011-06-24 17:16:57 -07001155 final int paddedTop = getPaddingTop();
1156 final int paddedBottom = mBottom - mTop - getPaddingBottom();
Adam Powell8d02dea2011-05-31 21:35:13 -07001157 ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
Adam Powell9ab97872010-10-26 21:47:29 -07001158 break;
1159 case Gravity.TOP:
1160 ypos = getPaddingTop() + topMargin;
1161 break;
1162 case Gravity.BOTTOM:
Adam Powell8d02dea2011-05-31 21:35:13 -07001163 ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight()
Adam Powell9ab97872010-10-26 21:47:29 -07001164 - bottomMargin;
1165 break;
1166 }
Adam Powell6556c072011-06-24 17:16:57 -07001167 final int customWidth = customView.getMeasuredWidth();
1168 customView.layout(xpos, ypos, xpos + customWidth,
1169 ypos + customView.getMeasuredHeight());
Adam Powell6231ab82012-06-22 14:08:11 -07001170 homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001171 x = next(x, customWidth, isLayoutRtl);
Adam Powell33b97432010-04-20 10:01:14 -07001172 }
Adam Powell6af97e12010-11-11 21:11:53 -08001173
1174 if (mProgressView != null) {
1175 mProgressView.bringToFront();
1176 final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
1177 mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
1178 mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
1179 }
Adam Powell6231ab82012-06-22 14:08:11 -07001180
1181 if (needsTouchDelegate) {
1182 mTempRect.set(homeLayout.getLeft(), homeLayout.getTop(),
1183 homeLayout.getRight() + homeSlop, homeLayout.getBottom());
1184 setTouchDelegate(new TouchDelegate(mTempRect, homeLayout));
1185 } else {
1186 setTouchDelegate(null);
1187 }
Adam Powell33b97432010-04-20 10:01:14 -07001188 }
1189
Adam Powell8d02dea2011-05-31 21:35:13 -07001190 @Override
Adam Powell9a5cc282011-08-28 16:18:16 -07001191 public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
Adam Powellaad47fd2011-08-17 17:33:33 -07001192 return new ActionBar.LayoutParams(getContext(), attrs);
1193 }
1194
1195 @Override
Adam Powell9a5cc282011-08-28 16:18:16 -07001196 public ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
Adam Powell8d02dea2011-05-31 21:35:13 -07001197 if (lp == null) {
1198 lp = generateDefaultLayoutParams();
1199 }
1200 return lp;
1201 }
1202
1203 @Override
1204 public Parcelable onSaveInstanceState() {
1205 Parcelable superState = super.onSaveInstanceState();
1206 SavedState state = new SavedState(superState);
1207
1208 if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
1209 state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
1210 }
1211
1212 state.isOverflowOpen = isOverflowMenuShowing();
1213
1214 return state;
1215 }
1216
1217 @Override
1218 public void onRestoreInstanceState(Parcelable p) {
1219 SavedState state = (SavedState) p;
1220
1221 super.onRestoreInstanceState(state.getSuperState());
1222
1223 if (state.expandedMenuItemId != 0 &&
1224 mExpandedMenuPresenter != null && mOptionsMenu != null) {
1225 final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId);
1226 if (item != null) {
1227 item.expandActionView();
1228 }
1229 }
1230
1231 if (state.isOverflowOpen) {
1232 postShowOverflowMenu();
1233 }
1234 }
1235
1236 static class SavedState extends BaseSavedState {
1237 int expandedMenuItemId;
1238 boolean isOverflowOpen;
1239
1240 SavedState(Parcelable superState) {
1241 super(superState);
1242 }
1243
1244 private SavedState(Parcel in) {
1245 super(in);
1246 expandedMenuItemId = in.readInt();
1247 isOverflowOpen = in.readInt() != 0;
1248 }
1249
1250 @Override
1251 public void writeToParcel(Parcel out, int flags) {
1252 super.writeToParcel(out, flags);
1253 out.writeInt(expandedMenuItemId);
1254 out.writeInt(isOverflowOpen ? 1 : 0);
1255 }
1256
1257 public static final Parcelable.Creator<SavedState> CREATOR =
1258 new Parcelable.Creator<SavedState>() {
1259 public SavedState createFromParcel(Parcel in) {
1260 return new SavedState(in);
1261 }
1262
1263 public SavedState[] newArray(int size) {
1264 return new SavedState[size];
1265 }
1266 };
1267 }
1268
Adam Powell2b0952b2011-03-09 00:15:38 -08001269 private static class HomeView extends FrameLayout {
1270 private View mUpView;
Adam Powell8d02dea2011-05-31 21:35:13 -07001271 private ImageView mIconView;
Adam Powellb1e2f252011-08-22 17:42:12 -07001272 private int mUpWidth;
Adam Powell2b0952b2011-03-09 00:15:38 -08001273
1274 public HomeView(Context context) {
1275 this(context, null);
1276 }
1277
1278 public HomeView(Context context, AttributeSet attrs) {
1279 super(context, attrs);
1280 }
1281
Adam Powell8d02dea2011-05-31 21:35:13 -07001282 public void setUp(boolean isUp) {
1283 mUpView.setVisibility(isUp ? VISIBLE : GONE);
1284 }
1285
1286 public void setIcon(Drawable icon) {
1287 mIconView.setImageDrawable(icon);
1288 }
1289
Adam Powell2b0952b2011-03-09 00:15:38 -08001290 @Override
Adam Powell7bc3ca02011-08-26 18:29:58 -07001291 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1292 onPopulateAccessibilityEvent(event);
1293 return true;
1294 }
1295
1296 @Override
1297 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
1298 super.onPopulateAccessibilityEvent(event);
1299 final CharSequence cdesc = getContentDescription();
1300 if (!TextUtils.isEmpty(cdesc)) {
1301 event.getText().add(cdesc);
1302 }
1303 }
1304
1305 @Override
1306 public boolean dispatchHoverEvent(MotionEvent event) {
1307 // Don't allow children to hover; we want this to be treated as a single component.
1308 return onHoverEvent(event);
1309 }
1310
1311 @Override
Adam Powell2b0952b2011-03-09 00:15:38 -08001312 protected void onFinishInflate() {
1313 mUpView = findViewById(com.android.internal.R.id.up);
1314 mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
1315 }
1316
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001317 public int getStartOffset() {
Adam Powellb1e2f252011-08-22 17:42:12 -07001318 return mUpView.getVisibility() == GONE ? mUpWidth : 0;
Adam Powell8d02dea2011-05-31 21:35:13 -07001319 }
1320
Adam Powell2b0952b2011-03-09 00:15:38 -08001321 @Override
1322 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1323 measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
1324 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
Adam Powellb1e2f252011-08-22 17:42:12 -07001325 mUpWidth = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
1326 int width = mUpView.getVisibility() == GONE ? 0 : mUpWidth;
Adam Powell2b0952b2011-03-09 00:15:38 -08001327 int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
1328 measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
1329 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
1330 width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
1331 height = Math.max(height,
1332 iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
Adam Powell0d5d1b7e2011-06-22 17:40:40 -07001333
1334 final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
1335 final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
1336 final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
1337 final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
1338
1339 switch (widthMode) {
1340 case MeasureSpec.AT_MOST:
1341 width = Math.min(width, widthSize);
1342 break;
1343 case MeasureSpec.EXACTLY:
1344 width = widthSize;
1345 break;
1346 case MeasureSpec.UNSPECIFIED:
1347 default:
1348 break;
1349 }
1350 switch (heightMode) {
1351 case MeasureSpec.AT_MOST:
1352 height = Math.min(height, heightSize);
1353 break;
1354 case MeasureSpec.EXACTLY:
1355 height = heightSize;
1356 break;
1357 case MeasureSpec.UNSPECIFIED:
1358 default:
1359 break;
1360 }
Adam Powell2b0952b2011-03-09 00:15:38 -08001361 setMeasuredDimension(width, height);
1362 }
1363
1364 @Override
1365 protected void onLayout(boolean changed, int l, int t, int r, int b) {
1366 final int vCenter = (b - t) / 2;
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001367 final boolean isLayoutRtl = isLayoutRtl();
1368 final int layoutDirection = getResolvedLayoutDirection();
1369 final int width = getWidth();
Adam Powellc8b0b002011-06-23 14:39:05 -07001370 int upOffset = 0;
Adam Powell2b0952b2011-03-09 00:15:38 -08001371 if (mUpView.getVisibility() != GONE) {
1372 final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
1373 final int upHeight = mUpView.getMeasuredHeight();
1374 final int upWidth = mUpView.getMeasuredWidth();
Adam Powellc8b0b002011-06-23 14:39:05 -07001375 upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001376 final int upTop = vCenter - upHeight / 2;
1377 final int upBottom = upTop + upHeight;
1378 final int upRight;
1379 final int upLeft;
1380 if (isLayoutRtl) {
1381 upRight = width;
1382 upLeft = upRight - upWidth;
1383 r -= upOffset;
1384 } else {
1385 upRight = upWidth;
1386 upLeft = 0;
1387 l += upOffset;
1388 }
1389 mUpView.layout(upLeft, upTop, upRight, upBottom);
Adam Powell2b0952b2011-03-09 00:15:38 -08001390 }
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001391
Adam Powell2b0952b2011-03-09 00:15:38 -08001392 final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001393 iconLp.onResolveLayoutDirection(layoutDirection);
Adam Powell2b0952b2011-03-09 00:15:38 -08001394 final int iconHeight = mIconView.getMeasuredHeight();
1395 final int iconWidth = mIconView.getMeasuredWidth();
1396 final int hCenter = (r - l) / 2;
Adam Powellc8b0b002011-06-23 14:39:05 -07001397 final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
Fabrice Di Megliocf1ba022012-06-25 15:49:11 -07001398 final int iconBottom = iconTop + iconHeight;
1399 final int iconLeft;
1400 final int iconRight;
1401 int marginStart = iconLp.getMarginStart();
1402 final int delta = Math.max(marginStart, hCenter - iconWidth / 2);
1403 if (isLayoutRtl) {
1404 iconRight = width - upOffset - delta;
1405 iconLeft = iconRight - iconWidth;
1406 } else {
1407 iconLeft = upOffset + delta;
1408 iconRight = iconLeft + iconWidth;
1409 }
1410 mIconView.layout(iconLeft, iconTop, iconRight, iconBottom);
Adam Powell2b0952b2011-03-09 00:15:38 -08001411 }
1412 }
Adam Powell8d02dea2011-05-31 21:35:13 -07001413
1414 private class ExpandedActionViewMenuPresenter implements MenuPresenter {
1415 MenuBuilder mMenu;
1416 MenuItemImpl mCurrentExpandedItem;
1417
1418 @Override
1419 public void initForMenu(Context context, MenuBuilder menu) {
1420 // Clear the expanded action view when menus change.
Adam Powell6b0e97c2011-08-03 12:06:32 -07001421 if (mMenu != null && mCurrentExpandedItem != null) {
1422 mMenu.collapseItemActionView(mCurrentExpandedItem);
Adam Powell8d02dea2011-05-31 21:35:13 -07001423 }
1424 mMenu = menu;
1425 }
1426
1427 @Override
1428 public MenuView getMenuView(ViewGroup root) {
1429 return null;
1430 }
1431
1432 @Override
1433 public void updateMenuView(boolean cleared) {
1434 // Make sure the expanded item we have is still there.
1435 if (mCurrentExpandedItem != null) {
1436 boolean found = false;
Adam Powellf35d0492011-08-17 13:56:47 -07001437
1438 if (mMenu != null) {
1439 final int count = mMenu.size();
1440 for (int i = 0; i < count; i++) {
1441 final MenuItem item = mMenu.getItem(i);
1442 if (item == mCurrentExpandedItem) {
1443 found = true;
1444 break;
1445 }
Adam Powell8d02dea2011-05-31 21:35:13 -07001446 }
1447 }
1448
1449 if (!found) {
1450 // The item we had expanded disappeared. Collapse.
1451 collapseItemActionView(mMenu, mCurrentExpandedItem);
1452 }
1453 }
1454 }
1455
1456 @Override
1457 public void setCallback(Callback cb) {
1458 }
1459
1460 @Override
1461 public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
1462 return false;
1463 }
1464
1465 @Override
1466 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
1467 }
1468
1469 @Override
1470 public boolean flagActionItems() {
1471 return false;
1472 }
1473
1474 @Override
1475 public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
1476 mExpandedActionView = item.getActionView();
Adam Powell28fa07e2011-07-15 20:17:25 -07001477 mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources()));
Adam Powell8d02dea2011-05-31 21:35:13 -07001478 mCurrentExpandedItem = item;
1479 if (mExpandedActionView.getParent() != ActionBarView.this) {
1480 addView(mExpandedActionView);
1481 }
1482 if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
1483 addView(mExpandedHomeLayout);
1484 }
1485 mHomeLayout.setVisibility(GONE);
Adam Powell15a16a82011-06-20 10:35:27 -07001486 if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
Adam Powell8d02dea2011-05-31 21:35:13 -07001487 if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
1488 if (mSpinner != null) mSpinner.setVisibility(GONE);
1489 if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
1490 requestLayout();
1491 item.setActionViewExpanded(true);
Adam Powell038f1c82011-07-21 14:28:10 -07001492
1493 if (mExpandedActionView instanceof CollapsibleActionView) {
1494 ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
1495 }
Amith Yamasani10da5902011-07-26 16:14:26 -07001496
Adam Powell8d02dea2011-05-31 21:35:13 -07001497 return true;
1498 }
1499
1500 @Override
1501 public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
Amith Yamasani10da5902011-07-26 16:14:26 -07001502 // Do this before detaching the actionview from the hierarchy, in case
1503 // it needs to dismiss the soft keyboard, etc.
1504 if (mExpandedActionView instanceof CollapsibleActionView) {
1505 ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
1506 }
1507
Adam Powell8d02dea2011-05-31 21:35:13 -07001508 removeView(mExpandedActionView);
1509 removeView(mExpandedHomeLayout);
Adam Powellb0e217e2011-08-12 11:36:51 -07001510 mExpandedActionView = null;
Adam Powell8d02dea2011-05-31 21:35:13 -07001511 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
1512 mHomeLayout.setVisibility(VISIBLE);
1513 }
1514 if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
Adam Powell15a16a82011-06-20 10:35:27 -07001515 if (mTitleLayout == null) {
1516 initTitle();
1517 } else {
1518 mTitleLayout.setVisibility(VISIBLE);
1519 }
Adam Powell8d02dea2011-05-31 21:35:13 -07001520 }
1521 if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
1522 mTabScrollView.setVisibility(VISIBLE);
1523 }
1524 if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) {
1525 mSpinner.setVisibility(VISIBLE);
1526 }
1527 if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
1528 mCustomNavView.setVisibility(VISIBLE);
1529 }
Adam Powell8d02dea2011-05-31 21:35:13 -07001530 mExpandedHomeLayout.setIcon(null);
1531 mCurrentExpandedItem = null;
1532 requestLayout();
1533 item.setActionViewExpanded(false);
Adam Powell038f1c82011-07-21 14:28:10 -07001534
Adam Powell8d02dea2011-05-31 21:35:13 -07001535 return true;
1536 }
Adam Powell11ed1d62011-07-11 21:19:59 -07001537
1538 @Override
1539 public int getId() {
1540 return 0;
1541 }
1542
1543 @Override
1544 public Parcelable onSaveInstanceState() {
1545 return null;
1546 }
1547
1548 @Override
1549 public void onRestoreInstanceState(Parcelable state) {
1550 }
Adam Powell8d02dea2011-05-31 21:35:13 -07001551 }
Adam Powell33b97432010-04-20 10:01:14 -07001552}