Merge "Turn ActionBar view recycling on" into jb-ub-mail
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;
-
     }
 
     /**