Changed tablet tabs to be a drop down spinner
The tabs in the action bar have been removed for the
tablet form factors and replaced with the action bar
drop down navigation list.
Also, this changes the list item padding in the browse
list on the 7" tablet to extend a little further on the
border to the contact detail panel in portrait mode, so
that more text of longer names can be seen.
Bug: 6426927
Change-Id: Ieced44f5241c3f4f71bdbd7818846e24076fb355
diff --git a/res/layout/people_navigation_item.xml b/res/layout/people_navigation_item.xml
new file mode 100644
index 0000000..b7d86d2
--- /dev/null
+++ b/res/layout/people_navigation_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the text view layout that is shown in the spinner for the navigation drop down menu on
+ tablet devices. The text appearance is governed via two styles:
+ PeopleNavigationDropDownHeaderTextAppearance - text appearance of the item in the header part
+ of navigation drop down list of the action bar.
+ PeopleNavigationDropDownTextAppearance - text appearance of the item in the drop down part of
+ the navigation drop down list of the action bar. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+/>
diff --git a/res/values-sw580dp-w940dp/styles.xml b/res/values-sw580dp-w940dp/styles.xml
new file mode 100644
index 0000000..07ef912
--- /dev/null
+++ b/res/values-sw580dp-w940dp/styles.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <style name="PeopleTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
+ <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
+ <item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
+ <item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
+ <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+ <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
+ <item name="android:textColorPrimary">@color/primary_text_color</item>
+ <item name="android:textColorSecondary">@color/secondary_text_color</item>
+ <item name="android:listViewStyle">@style/ListViewStyle</item>
+ <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
+ <item name="activated_background">@drawable/list_item_activated_background</item>
+ <item name="section_header_background">@drawable/list_title_holo</item>
+ <item name="list_item_divider">?android:attr/listDivider</item>
+ <item name="list_item_padding_top">0dip</item>
+ <item name="list_item_padding_right">24dip</item>
+ <item name="list_item_padding_bottom">0dip</item>
+ <item name="list_item_padding_left">0dip</item>
+ <item name="list_item_gap_between_image_and_text">8dip</item>
+ <item name="list_item_gap_between_label_and_data">5dip</item>
+ <item name="list_item_vertical_divider_margin">5dip</item>
+ <item name="list_item_presence_icon_margin">4dip</item>
+ <item name="list_item_photo_size">64dip</item>
+ <item name="list_item_profile_photo_size">80dip</item>
+ <item name="list_item_prefix_highlight_color">@color/people_app_theme_color</item>
+ <item name="list_item_header_text_indent">8dip</item>
+ <item name="list_item_header_text_size">14sp</item>
+ <item name="list_item_header_text_color">@color/people_app_theme_color</item>
+ <item name="list_item_header_height">32dip</item>
+ <item name="list_item_header_underline_height">1dip</item>
+ <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+ <item name="list_item_data_width_weight">5</item>
+ <item name="list_item_label_width_weight">3</item>
+ <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
+ <item name="list_item_contacts_count_text_size">12sp</item>
+ <item name="contact_browser_list_padding_left">0dip</item>
+ <item name="contact_browser_list_padding_right">0dip</item>
+ <item name="contact_browser_background">@android:color/transparent</item>
+ <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
+ <!-- Favorites -->
+ <item name="favorites_padding_bottom">0dip</item>
+ </style>
+
+</resources>
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index c387435..7a247ae 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -19,6 +19,7 @@
<item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
<item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
<item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+ <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
<item name="android:textColorPrimary">@color/primary_text_color</item>
<item name="android:textColorSecondary">@color/secondary_text_color</item>
<item name="android:listViewStyle">@style/ListViewStyle</item>
@@ -27,7 +28,7 @@
<item name="section_header_background">@drawable/list_title_holo</item>
<item name="list_item_divider">?android:attr/listDivider</item>
<item name="list_item_padding_top">0dip</item>
- <item name="list_item_padding_right">24dip</item>
+ <item name="list_item_padding_right">12dip</item>
<item name="list_item_padding_bottom">0dip</item>
<item name="list_item_padding_left">0dip</item>
<item name="list_item_gap_between_image_and_text">8dip</item>
diff --git a/res/values-sw680dp/styles.xml b/res/values-sw680dp/styles.xml
index 31de81b..3db3867 100644
--- a/res/values-sw680dp/styles.xml
+++ b/res/values-sw680dp/styles.xml
@@ -19,6 +19,7 @@
<item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
<item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
<item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+ <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
<item name="android:textColorPrimary">@color/primary_text_color</item>
<item name="android:textColorSecondary">@color/secondary_text_color</item>
<item name="android:listViewStyle">@style/ListViewStyle</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c375e8..93c130f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -363,7 +363,7 @@
This is especially valuable for views without textual representation like ImageView.
[CHAR LIMIT=NONE] -->
- <string name="contactsAllLabel">All</string>
+ <string name="contactsAllLabel">All contacts</string>
<!-- The content description text for the groups tab.
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3be1222..1702585 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -130,6 +130,7 @@
<item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
<item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
<item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+ <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
<item name="android:textColorPrimary">@color/primary_text_color</item>
<item name="android:textColorSecondary">@color/secondary_text_color</item>
<item name="android:listViewStyle">@style/ListViewStyle</item>
@@ -174,6 +175,9 @@
<item name="android:displayOptions"></item>
</style>
+ <style name="ContactsActionBarDropDownStyle" parent="@android:style/Widget.Holo.Light.Spinner">
+ </style>
+
<style name="ContactsActionBarTheme" parent="@android:style/Theme.Holo">
<item name="android:textColorHint">#CCCCCC</item>
<item name="android:textColor">@android:color/black</item>
@@ -343,4 +347,18 @@
<item name="android:singleLine">true</item>
<item name="android:textAllCaps">true</item>
</style>
+
+ <style name="PeopleNavigationDropDownTextAppearance">
+ <item name="android:textColor">#333333</item>
+ <item name="android:textSize">18sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textAllCaps">false</item>
+ </style>
+
+ <style name="PeopleNavigationDropDownHeaderTextAppearance">
+ <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textAllCaps">true</item>
+ </style>
</resources>
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index fd06d60..4fc9866 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -26,15 +26,19 @@
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.SharedPreferences;
+import android.graphics.Color;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
+import android.widget.ArrayAdapter;
import android.widget.SearchView;
import android.widget.SearchView.OnCloseListener;
import android.widget.SearchView.OnQueryTextListener;
+import android.widget.TextView;
/**
* Adapter for the action bar at the top of the Contacts activity.
@@ -74,7 +78,9 @@
private Listener mListener;
private final ActionBar mActionBar;
- private final MyTabListener mTabListener = new MyTabListener();
+ private final int mActionBarNavigationMode;
+ private final MyTabListener mTabListener;
+ private final MyNavigationListener mNavigationListener;
private boolean mShowHomeIcon;
private boolean mShowTabsAsText;
@@ -90,6 +96,34 @@
private int mCurrentTab = TabState.DEFAULT;
+ /**
+ * Extension of ArrayAdapter to be used for the action bar navigation drop list. It is not
+ * possible to change the text appearance of a text item that is in the spinner header or
+ * in the drop down list using a selector xml file. The only way to differentiate the two
+ * is if the view is gotten via {@link #getView(int, View, ViewGroup)} or
+ * {@link #getDropDownView(int, View, ViewGroup)}.
+ */
+ private class CustomArrayAdapter extends ArrayAdapter<String> {
+
+ public CustomArrayAdapter(Context context, int textResId) {
+ super(context, textResId);
+ }
+
+ public View getView (int position, View convertView, ViewGroup parent) {
+ TextView textView = (TextView) super.getView(position, convertView, parent);
+ textView.setTextAppearance(mContext,
+ R.style.PeopleNavigationDropDownHeaderTextAppearance);
+ return textView;
+ }
+
+ public View getDropDownView (int position, View convertView, ViewGroup parent) {
+ TextView textView = (TextView) super.getDropDownView(position, convertView, parent);
+ textView.setTextAppearance(mContext,
+ R.style.PeopleNavigationDropDownTextAppearance);
+ return textView;
+ }
+ }
+
public ActionBarAdapter(Context context, Listener listener, ActionBar actionBar,
boolean isUsingTwoPanes) {
mContext = context;
@@ -101,6 +135,15 @@
// On wide screens, show the tabs as text (instead of icons)
mShowTabsAsText = isUsingTwoPanes;
+ if (isUsingTwoPanes) {
+ mActionBarNavigationMode = ActionBar.NAVIGATION_MODE_LIST;
+ mTabListener = null;
+ mNavigationListener = new MyNavigationListener();
+ } else {
+ mActionBarNavigationMode = ActionBar.NAVIGATION_MODE_TABS;
+ mTabListener = new MyTabListener();
+ mNavigationListener = null;
+ }
// Set up search view.
View customSearchView = LayoutInflater.from(mActionBar.getThemedContext()).inflate(
@@ -124,12 +167,67 @@
mSearchView.setQuery(mQueryString, false);
mActionBar.setCustomView(customSearchView, layoutParams);
- // Set up tabs
+ // Set up tabs or navigation list
+ switch(mActionBarNavigationMode) {
+ case ActionBar.NAVIGATION_MODE_TABS:
+ setupTabs();
+ break;
+ case ActionBar.NAVIGATION_MODE_LIST:
+ setupNavigationList();
+ break;
+ }
+ }
+
+ private void setupTabs() {
addTab(TabState.GROUPS, R.drawable.ic_tab_groups, R.string.contactsGroupsLabel);
addTab(TabState.ALL, R.drawable.ic_tab_all, R.string.contactsAllLabel);
addTab(TabState.FAVORITES, R.drawable.ic_tab_starred, R.string.contactsFavoritesLabel);
}
+ private void setupNavigationList() {
+ ArrayAdapter<String> navAdapter = new CustomArrayAdapter(mContext,
+ R.layout.people_navigation_item);
+ navAdapter.add(mContext.getString(R.string.contactsAllLabel));
+ navAdapter.add(mContext.getString(R.string.contactsFavoritesLabel));
+ navAdapter.add(mContext.getString(R.string.contactsGroupsLabel));
+ mActionBar.setListNavigationCallbacks(navAdapter, mNavigationListener);
+ }
+
+ /**
+ * Because the navigation list items are in a different order than tab items, this returns
+ * the appropriate tab from the navigation item position.
+ */
+ private int getTabPositionFromNavigationItemPosition(int navItemPos) {
+ switch(navItemPos) {
+ case 0:
+ return TabState.ALL;
+ case 1:
+ return TabState.FAVORITES;
+ case 2:
+ return TabState.GROUPS;
+ }
+ throw new IllegalArgumentException(
+ "Parameter must be between 0 and " + Integer.toString(TabState.COUNT-1)
+ + " inclusive.");
+ }
+
+ /**
+ * This is the inverse of {@link getTabPositionFromNavigationItemPosition}.
+ */
+ private int getNavigationItemPositionFromTabPosition(int tabPos) {
+ switch(tabPos) {
+ case TabState.ALL:
+ return 0;
+ case TabState.FAVORITES:
+ return 1;
+ case TabState.GROUPS:
+ return 2;
+ }
+ throw new IllegalArgumentException(
+ "Parameter must be between 0 and " + Integer.toString(TabState.COUNT-1)
+ + " inclusive.");
+ }
+
public void initialize(Bundle savedState, ContactsRequest request) {
if (savedState == null) {
mSearchMode = request.isSearchMode();
@@ -189,6 +287,17 @@
}
}
+ private class MyNavigationListener implements ActionBar.OnNavigationListener {
+ public boolean mIgnoreNavigationItemSelected;
+
+ public boolean onNavigationItemSelected(int itemPosition, long itemId) {
+ if (!mIgnoreNavigationItemSelected) {
+ setCurrentTab(getTabPositionFromNavigationItemPosition(itemPosition));
+ }
+ return true;
+ }
+ }
+
/**
* Change the current tab, and notify the listener.
*/
@@ -205,9 +314,20 @@
}
mCurrentTab = tab;
- if ((mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS)
- && (mCurrentTab != mActionBar.getSelectedNavigationIndex())) {
- mActionBar.setSelectedNavigationItem(mCurrentTab);
+ final int actionBarSelectedNavIndex = mActionBar.getSelectedNavigationIndex();
+ switch(mActionBar.getNavigationMode()) {
+ case ActionBar.NAVIGATION_MODE_TABS:
+ if (mCurrentTab != actionBarSelectedNavIndex) {
+ mActionBar.setSelectedNavigationItem(mCurrentTab);
+ }
+ break;
+ case ActionBar.NAVIGATION_MODE_LIST:
+ if (mCurrentTab != getTabPositionFromNavigationItemPosition(
+ actionBarSelectedNavIndex)) {
+ mActionBar.setSelectedNavigationItem(
+ getNavigationItemPositionFromTabPosition(mCurrentTab));
+ }
+ break;
}
if (notifyListener && mListener != null) mListener.onSelectedTabChanged();
@@ -306,7 +426,9 @@
mListener.onAction(Action.START_SEARCH_MODE);
}
} else {
- if (mActionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_TABS) {
+ final int currentNavigationMode = mActionBar.getNavigationMode();
+ if (mActionBarNavigationMode == ActionBar.NAVIGATION_MODE_TABS
+ && currentNavigationMode != ActionBar.NAVIGATION_MODE_TABS) {
// setNavigationMode will trigger onTabSelected() with the tab which was previously
// selected.
// The issue is that when we're first switching to the tab navigation mode after
@@ -319,6 +441,13 @@
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mActionBar.setSelectedNavigationItem(mCurrentTab);
mTabListener.mIgnoreTabSelected = false;
+ } else if (mActionBarNavigationMode == ActionBar.NAVIGATION_MODE_LIST
+ && currentNavigationMode != ActionBar.NAVIGATION_MODE_LIST) {
+ mNavigationListener.mIgnoreNavigationItemSelected = true;
+ mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+ mActionBar.setSelectedNavigationItem(
+ getNavigationItemPositionFromTabPosition(mCurrentTab));
+ mNavigationListener.mIgnoreNavigationItemSelected = false;
}
mActionBar.setTitle(null);
// Since we have the {@link SearchView} in a custom action bar, we must manually handle