Skip to content

Commit a131f4e

Browse files
adampAndroid (Google) Code Review
authored andcommitted
Merge "Adjust action bar tab policies"
2 parents 09138a5 + b8139af commit a131f4e

File tree

11 files changed

+163
-26
lines changed

11 files changed

+163
-26
lines changed

core/java/com/android/internal/app/ActionBarImpl.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.android.internal.app;
1818

19+
import com.android.internal.view.ActionBarPolicy;
1920
import com.android.internal.view.menu.MenuBuilder;
2021
import com.android.internal.view.menu.MenuPopupHelper;
2122
import com.android.internal.view.menu.SubMenuBuilder;
@@ -183,18 +184,13 @@ private void init(View decor) {
183184
mContextDisplayMode = mActionView.isSplitActionBar() ?
184185
CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
185186

186-
// Older apps get the home button interaction enabled by default.
187-
// Newer apps need to enable it explicitly.
188-
setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion <
189-
Build.VERSION_CODES.ICE_CREAM_SANDWICH);
190-
191-
setHasEmbeddedTabs(mContext.getResources().getBoolean(
192-
com.android.internal.R.bool.action_bar_embed_tabs));
187+
ActionBarPolicy abp = ActionBarPolicy.get(mContext);
188+
setHomeButtonEnabled(abp.enableHomeButtonByDefault());
189+
setHasEmbeddedTabs(abp.hasEmbeddedTabs());
193190
}
194191

195192
public void onConfigurationChanged(Configuration newConfig) {
196-
setHasEmbeddedTabs(mContext.getResources().getBoolean(
197-
com.android.internal.R.bool.action_bar_embed_tabs));
193+
setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs());
198194
}
199195

200196
private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (C) 2012 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+
17+
package com.android.internal.view;
18+
19+
import com.android.internal.R;
20+
21+
import android.content.Context;
22+
import android.content.res.Resources;
23+
import android.content.res.TypedArray;
24+
import android.os.Build;
25+
import android.view.ViewConfiguration;
26+
27+
/**
28+
* Allows components to query for various configuration policy decisions
29+
* about how the action bar should lay out and behave on the current device.
30+
*/
31+
public class ActionBarPolicy {
32+
private Context mContext;
33+
34+
public static ActionBarPolicy get(Context context) {
35+
return new ActionBarPolicy(context);
36+
}
37+
38+
private ActionBarPolicy(Context context) {
39+
mContext = context;
40+
}
41+
42+
public int getMaxActionButtons() {
43+
return mContext.getResources().getInteger(R.integer.max_action_buttons);
44+
}
45+
46+
public boolean showsOverflowMenuButton() {
47+
return !ViewConfiguration.get(mContext).hasPermanentMenuKey();
48+
}
49+
50+
public int getEmbeddedMenuWidthLimit() {
51+
return mContext.getResources().getDisplayMetrics().widthPixels / 2;
52+
}
53+
54+
public boolean hasEmbeddedTabs() {
55+
final int targetSdk = mContext.getApplicationInfo().targetSdkVersion;
56+
if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
57+
return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs);
58+
}
59+
60+
// The embedded tabs policy changed in Jellybean; give older apps the old policy
61+
// so they get what they expect.
62+
return mContext.getResources().getBoolean(R.bool.action_bar_embed_tabs_pre_jb);
63+
}
64+
65+
public int getTabContainerHeight() {
66+
TypedArray a = mContext.obtainStyledAttributes(null, R.styleable.ActionBar,
67+
com.android.internal.R.attr.actionBarStyle, 0);
68+
int height = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
69+
Resources r = mContext.getResources();
70+
if (!hasEmbeddedTabs()) {
71+
// Stacked tabs; limit the height
72+
height = Math.min(height,
73+
r.getDimensionPixelSize(R.dimen.action_bar_stacked_max_height));
74+
}
75+
a.recycle();
76+
return height;
77+
}
78+
79+
public boolean enableHomeButtonByDefault() {
80+
// Older apps get the home button interaction enabled by default.
81+
// Newer apps need to enable it explicitly.
82+
return mContext.getApplicationInfo().targetSdkVersion <
83+
Build.VERSION_CODES.ICE_CREAM_SANDWICH;
84+
}
85+
86+
public int getStackedTabMaxWidth() {
87+
return mContext.getResources().getDimensionPixelSize(
88+
R.dimen.action_bar_stacked_tab_max_width);
89+
}
90+
}

core/java/com/android/internal/view/menu/ActionMenuPresenter.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.android.internal.view.menu;
1818

19+
import com.android.internal.view.ActionBarPolicy;
1920
import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
2021

2122
import android.content.Context;
@@ -29,7 +30,6 @@
2930
import android.view.SoundEffectConstants;
3031
import android.view.View;
3132
import android.view.View.MeasureSpec;
32-
import android.view.ViewConfiguration;
3333
import android.view.ViewGroup;
3434
import android.widget.ImageButton;
3535

@@ -79,17 +79,18 @@ public void initForMenu(Context context, MenuBuilder menu) {
7979

8080
final Resources res = context.getResources();
8181

82+
final ActionBarPolicy abp = ActionBarPolicy.get(context);
8283
if (!mReserveOverflowSet) {
83-
mReserveOverflow = !ViewConfiguration.get(context).hasPermanentMenuKey();
84+
mReserveOverflow = abp.showsOverflowMenuButton();
8485
}
8586

8687
if (!mWidthLimitSet) {
87-
mWidthLimit = res.getDisplayMetrics().widthPixels / 2;
88+
mWidthLimit = abp.getEmbeddedMenuWidthLimit();
8889
}
8990

9091
// Measure for initial configuration
9192
if (!mMaxItemsSet) {
92-
mMaxItems = res.getInteger(com.android.internal.R.integer.max_action_buttons);
93+
mMaxItems = abp.getMaxActionButtons();
9394
}
9495

9596
int width = mWidthLimit;

core/java/com/android/internal/widget/ScrollingTabContainerView.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@
1515
*/
1616
package com.android.internal.widget;
1717

18-
import com.android.internal.R;
18+
import com.android.internal.view.ActionBarPolicy;
1919

2020
import android.animation.Animator;
2121
import android.animation.ObjectAnimator;
2222
import android.animation.TimeInterpolator;
2323
import android.app.ActionBar;
2424
import android.content.Context;
2525
import android.content.res.Configuration;
26-
import android.content.res.TypedArray;
2726
import android.graphics.drawable.Drawable;
2827
import android.text.TextUtils.TruncateAt;
2928
import android.view.Gravity;
@@ -55,6 +54,7 @@ public class ScrollingTabContainerView extends HorizontalScrollView
5554
private boolean mAllowCollapse;
5655

5756
int mMaxTabWidth;
57+
int mStackedTabMaxWidth;
5858
private int mContentHeight;
5959
private int mSelectedTabIndex;
6060

@@ -69,10 +69,9 @@ public ScrollingTabContainerView(Context context) {
6969
super(context);
7070
setHorizontalScrollBarEnabled(false);
7171

72-
TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
73-
com.android.internal.R.attr.actionBarStyle, 0);
74-
setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
75-
a.recycle();
72+
ActionBarPolicy abp = ActionBarPolicy.get(context);
73+
setContentHeight(abp.getTabContainerHeight());
74+
mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
7675

7776
mTabLayout = createTabLayout();
7877
addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -93,6 +92,7 @@ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
9392
} else {
9493
mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
9594
}
95+
mMaxTabWidth = Math.min(mMaxTabWidth, mStackedTabMaxWidth);
9696
} else {
9797
mMaxTabWidth = -1;
9898
}
@@ -187,6 +187,7 @@ private LinearLayout createTabLayout() {
187187
final LinearLayout tabLayout = new LinearLayout(getContext(), null,
188188
com.android.internal.R.attr.actionBarTabBarStyle);
189189
tabLayout.setMeasureWithLargestChildEnabled(true);
190+
tabLayout.setGravity(Gravity.CENTER);
190191
tabLayout.setLayoutParams(new LinearLayout.LayoutParams(
191192
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
192193
return tabLayout;
@@ -205,12 +206,11 @@ private Spinner createSpinner() {
205206
protected void onConfigurationChanged(Configuration newConfig) {
206207
super.onConfigurationChanged(newConfig);
207208

209+
ActionBarPolicy abp = ActionBarPolicy.get(getContext());
208210
// Action bar can change size on configuration changes.
209211
// Reread the desired height from the theme-specified style.
210-
TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
211-
com.android.internal.R.attr.actionBarStyle, 0);
212-
setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
213-
a.recycle();
212+
setContentHeight(abp.getTabContainerHeight());
213+
mStackedTabMaxWidth = abp.getStackedTabMaxWidth();
214214
}
215215

216216
public void animateToVisibility(int visibility) {

core/res/res/values-port/bools.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 2012 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+
17+
<resources>
18+
<bool name="action_bar_embed_tabs">false</bool>
19+
</resources>

core/res/res/values-sw600dp/bools.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,5 @@
1717
<resources>
1818
<bool name="preferences_prefer_dual_pane">true</bool>
1919
<bool name="show_ongoing_ime_switcher">false</bool>
20-
<bool name="action_bar_expanded_action_views_exclusive">false</bool>
2120
<bool name="target_honeycomb_needs_options_menu">false</bool>
2221
</resources>

core/res/res/values-w480dp/bools.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
*/
1818
-->
1919
<resources>
20-
<bool name="action_bar_embed_tabs">true</bool>
20+
<bool name="action_bar_embed_tabs_pre_jb">true</bool>
2121
<bool name="split_action_bar_is_narrow">false</bool>
2222
</resources>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 2012 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+
17+
<resources>
18+
<bool name="action_bar_expanded_action_views_exclusive">false</bool>
19+
</resources>

core/res/res/values/bools.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
-->
1616

1717
<resources>
18-
<bool name="action_bar_embed_tabs">false</bool>
18+
<bool name="action_bar_embed_tabs">true</bool>
19+
<bool name="action_bar_embed_tabs_pre_jb">false</bool>
1920
<bool name="split_action_bar_is_narrow">true</bool>
2021
<bool name="preferences_prefer_dual_pane">false</bool>
2122
<bool name="show_ongoing_ime_switcher">true</bool>

core/res/res/values/dimens.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,13 @@
213213

214214
<!-- Minimum width for an action button in the menu area of an action bar -->
215215
<dimen name="action_button_min_width">56dip</dimen>
216+
217+
<!-- Maximum height for a stacked tab bar as part of an action bar -->
218+
<dimen name="action_bar_stacked_max_height">48dp</dimen>
219+
220+
<!-- Maximum width for a stacked action bar tab. This prevents
221+
action bar tabs from becoming too wide on a wide screen when only
222+
a few are present. -->
223+
<dimen name="action_bar_stacked_tab_max_width">180dp</dimen>
224+
216225
</resources>

0 commit comments

Comments
 (0)