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);
}