Turn ActionBar view recycling on
Part 2 of 2 to fix b/7017544
Change-Id: I96eeac825729c9a5cfaad96929085836f18923d4
diff --git a/res/layout/account_switch_spinner_dropdown_account.xml b/res/layout/account_switch_spinner_dropdown_account.xml
new file mode 100644
index 0000000..6aa09c1
--- /dev/null
+++ b/res/layout/account_switch_spinner_dropdown_account.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2011 Google Inc.
+ Licensed to 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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="?android:attr/spinnerDropDownItemStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/account_dropdown_item_height"
+ android:gravity="center_horizontal">
+ <View android:id="@+id/account_spinner_color"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_height="@dimen/color_block_height"
+ android:layout_width="@dimen/color_block_width"/>
+ <RelativeLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_centerVertical="true"
+ android:layout_alignParentLeft="true">
+
+ <!-- Something is strange here. Gmail1 allows for
+ two-line label names while Gmail2 does
+ not. TODO(viki): Fix. -->
+ <!-- In the IDs below: abd = ActionBarDropdown -->
+ <TextView
+ android:id="@+id/abd_account_first"
+ android:singleLine="true"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:ellipsize="end"
+ style="@android:style/TextAppearance.Holo.Widget.ActionBar.Title" />
+ <TextView
+ android:id="@+id/abd_account_second"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:ellipsize="end"
+ android:layout_below="@id/abd_account_first"
+ style="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle" />
+ </RelativeLayout>
+ <TextView
+ android:id="@+id/abd_account_unread"
+ style="@style/UnreadCount"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"/>
+</RelativeLayout>
diff --git a/res/layout/account_switch_spinner_dropdown_folder.xml b/res/layout/account_switch_spinner_dropdown_folder.xml
index fc72903..bdc4c59 100644
--- a/res/layout/account_switch_spinner_dropdown_folder.xml
+++ b/res/layout/account_switch_spinner_dropdown_folder.xml
@@ -20,7 +20,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <View android:id="@+id/account_spinner_color"
+ <!-- In the IDs below, ABD = ActionBarDropdown -->
+ <View android:id="@+id/abd_folder_color"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_height="@dimen/color_block_height"
@@ -40,22 +41,22 @@
<!-- Something is strange here. Gmail1 allows for two-line label names while Gmail2 does
not. TODO(viki): Fix. -->
<TextView
- android:id="@+id/account_spinner_first"
+ android:id="@+id/abd_folder_first"
android:singleLine="true"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:ellipsize="end"
style="@android:style/TextAppearance.Holo.Widget.ActionBar.Title" />
<TextView
- android:id="@+id/account_spinner_second"
+ android:id="@+id/abd_folder_second"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:ellipsize="end"
- android:layout_below="@id/account_spinner_first"
+ android:layout_below="@id/abd_folder_first"
style="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle" />
</RelativeLayout>
<TextView
- android:id="@+id/account_spinner_unread_count"
+ android:id="@+id/abd_folder_unread"
style="@style/UnreadCount"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"/>
diff --git a/res/layout/account_switch_spinner_dropdown_item.xml b/res/layout/account_switch_spinner_dropdown_item.xml
index 04a4f93..792b388 100644
--- a/res/layout/account_switch_spinner_dropdown_item.xml
+++ b/res/layout/account_switch_spinner_dropdown_item.xml
@@ -16,43 +16,34 @@
limitations under the License.
-->
-<RelativeLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/spinnerDropDownItemStyle"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/account_dropdown_item_height"
- android:gravity="center_horizontal">
- <View android:id="@+id/account_spinner_color"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:layout_height="@dimen/color_block_height"
- android:layout_width="@dimen/color_block_width"/>
- <RelativeLayout
- android:layout_height="wrap_content"
+ android:layout_height="match_parent">
+
+ <!-- Currently selected account -->
+ <include android:id="@+id/anchor"
+ layout="@layout/account_switch_spinner_item" />
+ <!-- All the dropdown choices -->
+ <FrameLayout android:id="@+id/dropdown"
android:layout_width="match_parent"
- android:layout_centerVertical="true"
- android:layout_alignParentLeft="true">
- <!-- Something is strange here. Gmail1 allows for two-line label names while Gmail2 does
- not. TODO(viki): Fix. -->
- <TextView
- android:id="@+id/account_spinner_first"
- android:singleLine="true"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:ellipsize="end"
- style="@android:style/TextAppearance.Holo.Widget.ActionBar.Title" />
- <TextView
- android:id="@+id/account_spinner_second"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:ellipsize="end"
- android:layout_below="@id/account_spinner_first"
- style="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle" />
- </RelativeLayout>
- <TextView
- android:id="@+id/account_spinner_unread_count"
- style="@style/UnreadCount"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"/>
-</RelativeLayout>
+ android:layout_height="wrap_content">
+
+ <!-- A normal account -->
+ <include android:id="@+id/account"
+ layout="@layout/account_switch_spinner_dropdown_account"/>
+
+ <!-- The header before the recent labels. -->
+ <include android:id="@+id/header"
+ layout="@layout/account_switch_spinner_dropdown_header"/>
+
+ <!-- Recent folder. -->
+ <include android:id="@+id/folder"
+ layout="@layout/account_switch_spinner_dropdown_folder"/>
+
+ <!-- Footer -->
+ <include android:id="@+id/footer"
+ layout="@layout/account_switch_spinner_dropdown_footer"/>
+
+ </FrameLayout>
+</FrameLayout>
diff --git a/res/layout/account_switch_spinner_item.xml b/res/layout/account_switch_spinner_item.xml
index 74a0cad..1723d71 100644
--- a/res/layout/account_switch_spinner_item.xml
+++ b/res/layout/account_switch_spinner_item.xml
@@ -25,8 +25,8 @@
android:layout_marginLeft="0dip">
<LinearLayout
- android:id="@+id/spinner"
android:layout_height="match_parent"
+ android:id="@+id/account_spinner"
android:orientation="vertical"
android:gravity="center_vertical"
android:background="@drawable/spinner_ab_holo_light"
@@ -34,7 +34,7 @@
android:layout_alignParentLeft="true"
style="@style/AccountSpinnerStyle">
<TextView
- android:id="@+id/account_spinner_first"
+ android:id="@+id/account_first"
style="@style/AccountSpinnerAnchorTextPrimary"
android:singleLine="true"
android:ellipsize="end"
@@ -42,7 +42,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
- android:id="@+id/account_spinner_second"
+ android:id="@+id/account_second"
style="@style/AccountSpinnerAnchorTextSecondary"
android:singleLine="true"
android:ellipsize="end"
@@ -53,8 +53,8 @@
</LinearLayout>
<TextView
- android:id="@+id/unread"
- android:layout_toRightOf="@id/spinner"
+ android:id="@+id/account_unread"
+ android:layout_toRightOf="@id/account_spinner"
android:layout_marginLeft="4dp"
style="@style/UnreadCountActionBar"/>
</RelativeLayout>
diff --git a/src/com/android/mail/AccountSpinnerAdapter.java b/src/com/android/mail/AccountSpinnerAdapter.java
index ae518fe..f191415 100644
--- a/src/com/android/mail/AccountSpinnerAdapter.java
+++ b/src/com/android/mail/AccountSpinnerAdapter.java
@@ -79,16 +79,18 @@
/** Maintains the most fresh default inbox folder for each account. Used for unread counts. */
private final FolderWatcher mFolderWatcher;
+ /** Type indicating the current account view shown in the actionbar (not the dropdown) */
+ private static final int TYPE_NON_DROPDOWN = 0;
/** Type indicating a dead, non-clickable view that is not shown to the user. */
- public static final int TYPE_DEAD_HEADER = -1;
+ public static final int TYPE_DEAD_HEADER = 1;
/** Type indicating an account (user@example.com). */
- public static final int TYPE_ACCOUNT = 0;
+ public static final int TYPE_ACCOUNT = 2;
/** Type indicating a view that separates the account list from the recent folder list. */
- public static final int TYPE_HEADER = 1;
+ public static final int TYPE_HEADER = 3;
/** Type indicating a view containing a recent folder (Sent, Outbox). */
- public static final int TYPE_FOLDER = 2;
+ public static final int TYPE_FOLDER = 4;
/** Type indicating the "Show All Folders" view. */
- public static final int TYPE_ALL_FOLDERS = 3;
+ public static final int TYPE_ALL_FOLDERS = 5;
private static final String LOG_TAG = LogTag.getLogTag();
@@ -142,6 +144,48 @@
}
/**
+ * Given a dropdown view, enable only the type, and disable everything else.
+ * @param view
+ * @param type
+ */
+ private static final void selectRelevant(View view, int type) {
+ if (view == null) {
+ return;
+ }
+ final View anchor = view.findViewById(R.id.anchor);
+ final View account = view.findViewById(R.id.account);
+ final View header = view.findViewById(R.id.header);
+ final View folder = view.findViewById(R.id.folder);
+ final View footer = view.findViewById(R.id.footer);
+ // Disable everything initially.
+ anchor.setVisibility(View.GONE);
+ account.setVisibility(View.GONE);
+ header.setVisibility(View.GONE);
+ folder.setVisibility(View.GONE);
+ footer.setVisibility(View.GONE);
+ switch (type) {
+ case TYPE_NON_DROPDOWN:
+ anchor.setVisibility(View.VISIBLE);
+ break;
+ case TYPE_DEAD_HEADER:
+ // Select nothing.
+ break;
+ case TYPE_ACCOUNT:
+ account.setVisibility(View.VISIBLE);
+ break;
+ case TYPE_HEADER:
+ header.setVisibility(View.VISIBLE);
+ break;
+ case TYPE_FOLDER:
+ folder.setVisibility(View.VISIBLE);
+ break;
+ case TYPE_ALL_FOLDERS:
+ footer.setVisibility(View.VISIBLE);
+ break;
+ }
+ }
+
+ /**
* Given a position in the list, what offset does it correspond to in the Recent Folders
* list?
* @param position
@@ -290,13 +334,15 @@
@Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
- view = mInflater.inflate(R.layout.account_switch_spinner_item, null);
+ view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_item, null);
}
- ((TextView) view.findViewById(R.id.account_spinner_first)).setText(getFolderLabel());
- ((TextView) view.findViewById(R.id.account_spinner_second))
+ selectRelevant(view, TYPE_NON_DROPDOWN);
+ ((TextView) view.findViewById(R.id.account_first)).setText(getFolderLabel());
+ ((TextView) view.findViewById(R.id.account_second))
.setText(getCurrentAccountName());
final int currentViewUnreadCount = getFolderUnreadCount();
- populateUnreadCountView((TextView) view.findViewById(R.id.unread), currentViewUnreadCount);
+ populateUnreadCountView((TextView) view.findViewById(R.id.account_unread),
+ currentViewUnreadCount);
return view;
}
@@ -319,23 +365,18 @@
// Shown in the second text view with smaller font.
String smallText = "";
int unreadCount = 0;
- // Do not use view recycling in getDropDownView!!!
- //
- // We cannot use view recycling here: view should always be instantiated. The reason is that
- // spinners cannot deal with different view types. They expect every view to be identical.
- // The previous implementation used a single view, which was a union of all the different
- // views we would show in a dropdown, but that led to an increase in the number of views
- // for the dropdown window. The account spinner dropdown is a separate window, and when the
- // dropdown is dismissed, all the views are removed. Tapping on the account spinner creates
- // a new popup window, and all the views need to be recreated from scratch. Since all the
- // views are recreated, it should be reasonable to instantiate a view for each dropdown
- // element as opposed to recycling them.
- switch (getType(position)) {
+ // Do not use stop view recycling in getDropDownView!!!
+ // For unknown reasons, using view recycling avoids bugs where the unread count used to
+ // disappear.
+ final int type = getType(position);
+ if (view == null) {
+ view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_item, null);
+ }
+ selectRelevant(view, type);
+ switch (type) {
case TYPE_DEAD_HEADER:
- view = mInflater.inflate(R.layout.empty, null);
return view;
case TYPE_ACCOUNT:
- view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_item, null);
final Account account = getAccount(position);
View colorView = view.findViewById(R.id.account_spinner_color);
if (account == null) {
@@ -356,32 +397,31 @@
final Folder inbox = mFolderWatcher.get(account.settings.defaultInbox);
unreadCount = (inbox != null) ? inbox.unreadCount : 0;
}
+ displayOrHide(view, R.id.abd_account_first, bigText);
+ displayOrHide(view, R.id.abd_account_second, smallText);
+ populateUnreadCountView(
+ (TextView) view.findViewById(R.id.abd_account_unread), unreadCount);
break;
case TYPE_HEADER:
- view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_header, null);
((TextView) view.findViewById(R.id.account_spinner_header_account))
.setText(getCurrentAccountName());
return view;
case TYPE_FOLDER:
- view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_folder, null);
final Folder folder = mRecentFolderList.get(getRecentOffset(position));
- colorView = view.findViewById(R.id.account_spinner_color);
+ colorView = view.findViewById(R.id.abd_folder_color);
bigText = folder.name;
unreadCount = folder.unreadCount;
Folder.setFolderBlockColor(folder, colorView);
colorView.setVisibility(View.VISIBLE);
+ displayOrHide(view, R.id.abd_folder_first, bigText);
+ displayOrHide(view, R.id.abd_folder_second, smallText);
+ populateUnreadCountView(
+ (TextView) view.findViewById(R.id.abd_folder_unread), unreadCount);
break;
case TYPE_ALL_FOLDERS:
- view = mInflater.inflate(R.layout.account_switch_spinner_dropdown_footer, null);
return view;
}
- displayOrHide(view, R.id.account_spinner_first, bigText);
- displayOrHide(view, R.id.account_spinner_second, smallText);
- populateUnreadCountView(
- (TextView) view.findViewById(R.id.account_spinner_unread_count),
- unreadCount);
return view;
-
}
/**