Contact detail list changes

- Bring back DataKind header labels
- Fix dividers
- Add networks section for 3rd party entries
- Move phonetic name (previously in header) into list of contact details
- Move attribution (previously in header) under networks section
- Rearrange ordering of DataKind sections according to mocks
- Do some minor re-styling for phone

Change-Id: Ic49e521e122b00a6038b0679f21b90e2323b9171
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml b/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml
index 9ad0e1b..2de488d 100644
--- a/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml
+++ b/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml
@@ -43,7 +43,9 @@
 
                 <TextView
                     android:id="@+id/kind"
-                    style="@style/ContactDetailItemType" />
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:visibility="gone" />
 
                 <TextView
                     android:id="@+id/type"
@@ -83,7 +85,7 @@
                 android:scaleType="centerInside" />
 
             <View
-                android:id="@+id/divider"
+                android:id="@+id/vertical_divider"
                 android:layout_width="1px"
                 android:layout_height="match_parent"
                 android:layout_marginTop="5dip"
diff --git a/res/layout-sw580dp/simple_contact_detail_header_view_list_item.xml b/res/layout-sw580dp/simple_contact_detail_header_view_list_item.xml
index b14d563..5960022 100644
--- a/res/layout-sw580dp/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout-sw580dp/simple_contact_detail_header_view_list_item.xml
@@ -46,18 +46,6 @@
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium" />
 
-    <TextView
-        android:id="@+id/phonetic_name"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceSmall" />
-
-    <TextView
-        android:id="@+id/attribution"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceSmall" />
-
     <CheckBox
         android:id="@+id/star"
         android:layout_width="wrap_content"
diff --git a/res/layout/contact_detail_kind_title_entry_view.xml b/res/layout/contact_detail_kind_title_entry_view.xml
new file mode 100644
index 0000000..379cbe1
--- /dev/null
+++ b/res/layout/contact_detail_kind_title_entry_view.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2011, 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.
+ */
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingLeft="@dimen/detail_item_side_margin"
+    android:paddingRight="@dimen/detail_item_side_margin"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/kind"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textColor="@color/detail_kind_title_color"
+        android:textStyle="bold"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:paddingTop="5dip"
+        android:paddingBottom="2dip" />
+
+    <View
+        android:id="@+id/kind_divider"
+        android:layout_width="match_parent"
+        android:layout_height="2dip"
+        android:background="@color/detail_kind_title_color"/>
+
+</LinearLayout>
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index 2e4a3e5..a116cb3 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -22,6 +22,9 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingLeft="@dimen/detail_item_side_margin"
+    android:paddingRight="@dimen/detail_item_side_margin"
+    android:paddingTop="@dimen/detail_item_vertical_margin"
+    android:paddingBottom="@dimen/detail_item_vertical_margin"
     android:orientation="horizontal"
     android:gravity="center_vertical">
 
@@ -34,27 +37,29 @@
 
         <TextView
             android:id="@+id/kind"
-            style="@style/ContactDetailItemType" />
-
-        <TextView
-            android:id="@+id/type"
-            style="@style/ContactDetailItemType" />
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone" />
 
         <TextView
             android:id="@+id/data"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
-            android:paddingBottom="5dip"
             android:textAppearance="?android:attr/textAppearanceMedium" />
 
         <TextView
+            android:id="@+id/type"
+            style="@style/ContactDetailItemType" />
+
+        <TextView
             android:id="@+id/footer"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:visibility="gone" />
+
     </LinearLayout>
 
     <ImageView
@@ -66,7 +71,7 @@
         android:scaleType="centerInside" />
 
     <View
-        android:id="@+id/divider"
+        android:id="@+id/vertical_divider"
         android:layout_width="1px"
         android:layout_height="match_parent"
         android:layout_marginTop="15dip"
diff --git a/res/layout/contact_detail_separator_list_item.xml b/res/layout/contact_detail_separator_entry_view.xml
similarity index 68%
rename from res/layout/contact_detail_separator_list_item.xml
rename to res/layout/contact_detail_separator_entry_view.xml
index 87f0597..abdca5f 100644
--- a/res/layout/contact_detail_separator_list_item.xml
+++ b/res/layout/contact_detail_separator_entry_view.xml
@@ -14,9 +14,15 @@
      limitations under the License.
 -->
 
-<View xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginTop="8dip"
-    android:background="@drawable/divider_horizontal_light"
-    />
\ No newline at end of file
+    android:paddingLeft="@dimen/detail_item_side_margin"
+    android:paddingRight="@dimen/detail_item_side_margin">
+
+    <View
+      android:layout_width="match_parent"
+      android:layout_height="1dip"
+      android:background="?android:attr/listDivider"/>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/simple_contact_detail_header_view_list_item.xml b/res/layout/simple_contact_detail_header_view_list_item.xml
index 0c0867f..eea4ac4 100644
--- a/res/layout/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout/simple_contact_detail_header_view_list_item.xml
@@ -14,17 +14,10 @@
      limitations under the License.
 -->
 
-<!--
-  This view temporarily holds the extra information that used to be in the
-  original contact detail header view, but now must move into the list because
-  of the new tab carousel. TODO: Integrate this better into the list as provided
-  by the mocks.
--->
-<LinearLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:layout_height="wrap_content">
 
     <ImageView
         android:id="@+id/photo"
@@ -32,18 +25,4 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/detail_tab_carousel_height" />
 
-    <TextView
-        android:id="@+id/phonetic_name"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:padding="10dip"
-        android:textAppearance="?android:attr/textAppearanceSmall" />
-
-    <TextView
-        android:id="@+id/attribution"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:padding="10dip"
-        android:textAppearance="?android:attr/textAppearanceSmall" />
-
-</LinearLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index b34efcc..32d02be 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -112,7 +112,7 @@
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
         <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
-        <item name="android:textColor">@color/detail_item_type_color</item>
+        <item name="android:textColor">?android:attr/textColorTertiary</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">marquee</item>
         <item name="android:gravity">center_vertical</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9d726e2..496d55f 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -43,6 +43,9 @@
     <!-- Color of the line above the contact photo in the contact detail header -->
     <color name="contact_detail_header_divider_color">#FF999999</color>
 
+    <!-- Color of the title text and divider for the kind type on the contact detail page -->
+    <color name="detail_kind_title_color">#63B8FF</color>
+
     <!-- Color of the text indicating the type of entry (e.g. Home, Work etc) -->
     <color name="detail_item_type_color">#B4B4B4</color>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d248f5b..7ab889c 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -116,7 +116,10 @@
     <dimen name="detail_item_icon_margin">10dip</dimen>
 
     <!-- Left and right padding for a contact detail item -->
-    <dimen name="detail_item_side_margin">10dip</dimen>
+    <dimen name="detail_item_side_margin">16dip</dimen>
+
+    <!-- Top and bottom padding for a contact detail item -->
+    <dimen name="detail_item_vertical_margin">12dip</dimen>
 
     <!-- Minimum height of a row in the contact detail -->
     <dimen name="detail_min_line_item_height">48dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4103060..0e47ebb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1262,6 +1262,9 @@
     <!-- Field title for the phonetic name of a contact [CHAR LIMIT=64]-->
     <string name="name_phonetic">Phonetic name</string>
 
+    <!-- Title for the list of all contact details that come from third-party sources (including a corporate directory) [CHAR LIMIT=20] -->
+    <string name="network">Network</string>
+
     <!-- String describing which account type a contact came from when editing it -->
     <string name="account_type_format"><xliff:g id="source" example="Gmail">%1$s</xliff:g> contact</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index fbd8653..2abfaa2 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -276,12 +276,11 @@
     <style name="ContactDetailItemType">
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
-        <item name="android:textColor">@color/detail_item_type_color</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+        <item name="android:textColor">?android:attr/textColorTertiary</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">marquee</item>
         <item name="android:gravity">center_vertical</item>
-        <item name="android:paddingTop">5dip</item>
     </style>
 
     <style name="GroupBrowseListItem">
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 180389f..1f7fac8 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -419,7 +419,7 @@
         Collapser.collapseList(mImEntries);
 
         // Make one aggregated list of all entries for display to the user.
-        flattenAllLists();
+        setupFlattenedList();
 
         if (mAdapter == null) {
             mAdapter = new ViewAdapter();
@@ -689,39 +689,110 @@
      * Collapse all contact detail entries into one aggregated list with a {@link HeaderViewEntry}
      * at the top.
      */
-    private void flattenAllLists() {
+    private void setupFlattenedList() {
         // All contacts should have a header view (even if there is no data for the contact).
         mAllEntries.add(new HeaderViewEntry());
 
+        addPhoneticName();
+
         flattenList(mPhoneEntries);
         flattenList(mSmsEntries);
         flattenList(mEmailEntries);
         flattenList(mImEntries);
-        flattenList(mPostalEntries);
         flattenList(mNicknameEntries);
-        flattenList(mNoteEntries);
         flattenList(mWebsiteEntries);
+
+        addNetworks();
+
         flattenList(mSipEntries);
+        flattenList(mPostalEntries);
         flattenList(mEventEntries);
-        flattenList(mOtherEntries);
-        flattenList(mRelationEntries);
         flattenList(mGroupEntries);
+        flattenList(mRelationEntries);
+        flattenList(mNoteEntries);
+    }
+
+    /**
+     * Add phonetic name (if applicable) to the aggregated list of contact details. This has to be
+     * done manually because phonetic name doesn't have a mimetype or action intent.
+     */
+    private void addPhoneticName() {
+        String phoneticName = ContactDetailDisplayUtils.getPhoneticName(mContext, mContactData);
+        if (TextUtils.isEmpty(phoneticName)) {
+            return;
+        }
+
+        // Add a title
+        String phoneticNameKindTitle = mContext.getString(R.string.name_phonetic);
+        mAllEntries.add(new KindTitleViewEntry(phoneticNameKindTitle.toUpperCase()));
+
+        // Add the phonetic name
+        final DetailViewEntry entry = new DetailViewEntry();
+        entry.kind = phoneticNameKindTitle;
+        entry.data = phoneticName;
+        mAllEntries.add(entry);
+    }
+
+    /**
+     * Add attribution and other third-party entries (if applicable) under the "networks" section
+     * of the aggregated list of contact details. This has to be done manually because the
+     * attribution does not have a mimetype and the third-party entries don't have actually belong
+     * to the same {@link DataKind}.
+     */
+    private void addNetworks() {
+        String attribution = ContactDetailDisplayUtils.getAttribution(mContext, mContactData);
+        boolean hasAttribution = !TextUtils.isEmpty(attribution);
+        int otherEntriesSize = mOtherEntries.size();
+        if (!hasAttribution && otherEntriesSize == 0) {
+            return;
+        }
+
+        // Add a title
+        String networkKindTitle = mContext.getString(R.string.network);
+        mAllEntries.add(new KindTitleViewEntry(networkKindTitle.toUpperCase()));
+
+        // Add the attribution if applicable
+        if (hasAttribution) {
+            final DetailViewEntry entry = new DetailViewEntry();
+            entry.kind = networkKindTitle;
+            entry.data = attribution;
+            mAllEntries.add(entry);
+        }
+
+        // Add the other entries from third parties
+        for (int i = 0; i < otherEntriesSize; i++) {
+            // Add a divider above the entry. Don't add an entry above the first one if it's the
+            // first one in the DataKind.
+            if (i != 0 || (i == 0 && hasAttribution)) {
+                mAllEntries.add(new SeparatorViewEntry());
+            }
+            mAllEntries.add(mOtherEntries.get(i));
+        }
+
+        mOtherEntries.clear();
     }
 
     /**
      * Iterate through {@link DetailViewEntry} in the given list and add it to a list of all
-     * entries. Add a {@link SeparatorViewEntry} at the end if the length of the list was not 0.
-     * Clear the original list.
+     * entries. Add a {@link KindTitleViewEntry} at the start if the length of the list is not 0.
+     * Add {@link SeparatorViewEntry}s as dividers as appropriate. Clear the original list.
      */
     private void flattenList(ArrayList<DetailViewEntry> entries) {
         int count = entries.size();
 
-        for (int i = 0; i < count; i++) {
-            mAllEntries.add(entries.get(i));
+        // Add a title for this kind by extracting the kind from the first entry
+        if (count > 0) {
+            String kind = entries.get(0).kind;
+            mAllEntries.add(new KindTitleViewEntry(kind.toUpperCase()));
         }
 
-        if (count > 0) {
-            mAllEntries.add(new SeparatorViewEntry());
+        // Add all the data entries for this kind
+        for (int i = 0; i < count; i++) {
+            // For all entries except the first one, add a divider above the entry
+            if (i != 0) {
+                mAllEntries.add(new SeparatorViewEntry());
+            }
+            mAllEntries.add(entries.get(i));
         }
 
         // Clear old list because it's not needed anymore.
@@ -863,7 +934,7 @@
     /**
      * Header item in the {@link ViewAdapter} list of data.
      */
-    static class HeaderViewEntry extends ViewEntry {
+    private static class HeaderViewEntry extends ViewEntry {
 
         HeaderViewEntry() {
             super(ViewAdapter.VIEW_TYPE_HEADER_ENTRY);
@@ -875,7 +946,7 @@
      * Separator between items of the same {@link DataKind} in the
      * {@link ViewAdapter} list of data.
      */
-    static class SeparatorViewEntry extends ViewEntry {
+    private static class SeparatorViewEntry extends ViewEntry {
 
         SeparatorViewEntry() {
             super(ViewAdapter.VIEW_TYPE_SEPARATOR_ENTRY);
@@ -884,6 +955,21 @@
     }
 
     /**
+     * Title entry for items of the same {@link DataKind} in the
+     * {@link ViewAdapter} list of data.
+     */
+    private static class KindTitleViewEntry extends ViewEntry {
+
+        public final String title;
+
+        KindTitleViewEntry(String titleText) {
+            super(ViewAdapter.VIEW_TYPE_KIND_TITLE_ENTRY);
+            title = titleText;
+        }
+
+    }
+
+    /**
      * An item with a single detail for a contact in the {@link ViewAdapter}
      * list of data.
      */
@@ -1055,8 +1141,9 @@
 
         public static final int VIEW_TYPE_DETAIL_ENTRY = 0;
         public static final int VIEW_TYPE_HEADER_ENTRY = 1;
-        public static final int VIEW_TYPE_SEPARATOR_ENTRY = 2;
-        private static final int VIEW_TYPE_COUNT = 3;
+        public static final int VIEW_TYPE_KIND_TITLE_ENTRY = 2;
+        public static final int VIEW_TYPE_SEPARATOR_ENTRY = 3;
+        private static final int VIEW_TYPE_COUNT = 4;
 
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
@@ -1065,6 +1152,8 @@
                     return getHeaderEntryView(convertView, parent);
                 case VIEW_TYPE_SEPARATOR_ENTRY:
                     return getSeparatorEntryView(convertView, parent);
+                case VIEW_TYPE_KIND_TITLE_ENTRY:
+                    return getKindTitleEntryView(position, convertView, parent);
                 case VIEW_TYPE_DETAIL_ENTRY:
                     return getDetailEntryView(position, convertView, parent);
                 default:
@@ -1132,7 +1221,18 @@
             if (convertView != null) {
                 return convertView;
             }
-            return mInflater.inflate(R.layout.contact_detail_separator_list_item, parent, false);
+            return mInflater.inflate(R.layout.contact_detail_separator_entry_view, parent, false);
+        }
+
+        private View getKindTitleEntryView(int position, View convertView, ViewGroup parent) {
+            final KindTitleViewEntry entry = (KindTitleViewEntry) getItem(position);
+
+            final View result = (convertView != null) ? convertView :
+                    mInflater.inflate(R.layout.contact_detail_kind_title_entry_view, parent, false);
+            final TextView titleTextView = (TextView) result.findViewById(R.id.kind);
+            titleTextView.setText(entry.title);
+
+            return result;
         }
 
         private View getDetailEntryView(int position, View convertView, ViewGroup parent) {
@@ -1161,36 +1261,21 @@
                         R.id.secondary_action_button_container);
                 viewCache.secondaryActionButtonContainer.setOnClickListener(
                         mSecondaryActionClickListener);
-                viewCache.secondaryActionDivider = v.findViewById(R.id.divider);
+                viewCache.secondaryActionDivider = v.findViewById(R.id.vertical_divider);
                 v.setTag(viewCache);
             }
 
-            final ViewEntry previousEntry = position == 0 ? null : getItem(position - 1);
-            final boolean isFirstOfItsKind = (previousEntry == null) ? true :
-                    (previousEntry.getViewType() != VIEW_TYPE_DETAIL_ENTRY);
-
-            // Bind the data to the view
-            bindView(v, entry, isFirstOfItsKind);
+            bindView(v, entry);
             return v;
         }
 
-        private void bindView(View view, DetailViewEntry entry, boolean isFirstOfItsKind) {
+        private void bindView(View view, DetailViewEntry entry) {
             final Resources resources = mContext.getResources();
             ViewCache views = (ViewCache) view.getTag();
 
-            if (isFirstOfItsKind) {
-                views.kind.setText(entry.kind != null ? entry.kind.toUpperCase() : "");
-                views.kind.setVisibility(View.VISIBLE);
-            } else {
-                views.kind.setVisibility(View.GONE);
-            }
-
             if (!TextUtils.isEmpty(entry.typeString)) {
                 views.type.setText(entry.typeString.toUpperCase());
                 views.type.setVisibility(View.VISIBLE);
-                if (isFirstOfItsKind) {
-                    views.kind.setVisibility(View.GONE);
-                }
             } else {
                 views.type.setVisibility(View.GONE);
             }