Merge "Make ContactPreferences use SharedPreferences instead of System settings (2/5)" into lmp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 30480c2..69d211e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,6 +20,7 @@
<original-package android:name="com.android.contacts" />
+ <uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CALL_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
diff --git a/res/drawable/action_bar_tab.xml b/res/drawable/action_bar_tab.xml
new file mode 100644
index 0000000..3982a3b
--- /dev/null
+++ b/res/drawable/action_bar_tab.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/tab_pressed_color">
+ <item>
+ <selector>
+ <item android:drawable="@drawable/tab_selected"
+ android:state_focused="false"
+ android:state_pressed="false"
+ android:state_selected="true" />
+ <item android:drawable="@drawable/tab_selected_focused"
+ android:state_focused="true"
+ android:state_pressed="false"
+ android:state_selected="true" />
+ <item android:drawable="@drawable/tab_unselected_focused"
+ android:state_focused="true"
+ android:state_pressed="false"
+ android:state_selected="false" />
+ <item android:drawable="@drawable/tab_selected"
+ android:state_selected="true" />
+ <item android:drawable="@color/tab_default_color" />
+ </selector>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/res/drawable/tab_selected.xml b/res/drawable/tab_selected.xml
new file mode 100644
index 0000000..9eec3c4
--- /dev/null
+++ b/res/drawable/tab_selected.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <!-- Tab selected underline -->
+ <item android:drawable="@color/tab_selected_color" />
+ <!-- Tab background -->
+ <item android:drawable="@color/tab_default_color"
+ android:bottom="@dimen/tab_selected_underline_height" />
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/tab_selected_focused.xml b/res/drawable/tab_selected_focused.xml
new file mode 100644
index 0000000..ba5162a
--- /dev/null
+++ b/res/drawable/tab_selected_focused.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <!-- Tab selected underline -->
+ <item android:drawable="@color/tab_selected_color" />
+ <!-- Tab background -->
+ <item android:drawable="@color/tab_default_color"
+ android:bottom="@dimen/tab_selected_underline_height" />
+ <!-- Focus rectangle -->
+ <item>
+ <shape android:shape="rectangle" >
+ <stroke
+ android:width="@dimen/tab_focused_stroke_width"
+ android:color="@color/focus_color" />
+ </shape>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/tab_unselected_focused.xml b/res/drawable/tab_unselected_focused.xml
new file mode 100644
index 0000000..1e4c6c3
--- /dev/null
+++ b/res/drawable/tab_unselected_focused.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Tab background -->
+ <item android:drawable="@color/tab_default_color" />
+ <!-- Focus rectangle -->
+ <item>
+ <shape android:shape="rectangle" >
+ <stroke
+ android:width="@dimen/tab_focused_stroke_width"
+ android:color="@color/focus_color" />
+ </shape>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/layout/edit_date_picker.xml b/res/layout/edit_date_picker.xml
index b84a8d5..ce9a85f 100644
--- a/res/layout/edit_date_picker.xml
+++ b/res/layout/edit_date_picker.xml
@@ -20,7 +20,7 @@
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/date_view"
- style="?android:attr/spinnerStyle"
+ style="@style/SpinnerButtonStyle"
android:layout_width="0dip"
android:layout_height="@dimen/editor_min_line_item_height"
android:layout_weight="1"
diff --git a/res/layout/expanding_entry_card_item.xml b/res/layout/expanding_entry_card_item.xml
index 99738a6..9195800 100644
--- a/res/layout/expanding_entry_card_item.xml
+++ b/res/layout/expanding_entry_card_item.xml
@@ -19,7 +19,7 @@
style="@style/SelectableItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="@dimen/expanding_entry_card_item_padding_with_image_start"
+ android:paddingStart="@dimen/expanding_entry_card_item_padding_start"
android:paddingEnd="@dimen/expanding_entry_card_item_padding_end"
android:paddingTop="@dimen/expanding_entry_card_item_padding_top"
android:paddingBottom="@dimen/expanding_entry_card_item_padding_bottom">
@@ -31,7 +31,8 @@
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="@dimen/expanding_entry_card_item_image_spacing"
- android:scaleType="fitCenter" />
+ android:scaleType="fitCenter"
+ android:layout_marginTop="@dimen/expanding_entry_card_item_icon_margin_top" />
<TextView
android:id="@+id/header"
@@ -40,7 +41,7 @@
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/icon"
android:singleLine="true"
- android:textColor="@android:color/black" />
+ android:textColor="@color/quickcontact_entry_header_text_color" />
<TextView
android:id="@+id/sub_header"
@@ -48,7 +49,7 @@
android:layout_height="wrap_content"
android:layout_below="@+id/header"
android:layout_toEndOf="@+id/icon_sub_header"
- android:textColor="@android:color/black" />
+ android:textColor="@color/quickcontact_entry_sub_header_text_color" />
<ImageView
android:layout_width="wrap_content"
@@ -65,7 +66,7 @@
android:id="@+id/text"
android:layout_below="@+id/sub_header"
android:layout_toEndOf="@+id/icon_text"
- android:textColor="@android:color/darker_gray"/>
+ android:textColor="@color/quickcontact_entry_sub_header_text_color" />
<ImageView
android:layout_width="wrap_content"
@@ -76,4 +77,15 @@
android:layout_marginTop="@dimen/expanding_entry_card_item_text_icon_margin_top"
android:layout_marginEnd="@dimen/expanding_entry_card_item_text_icon_margin_right" />
-</RelativeLayout>
\ No newline at end of file
+ <ImageView
+ android:id="@+id/icon_alternate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:visibility="gone"
+ android:layout_marginEnd="@dimen/expanding_entry_card_item_alternate_icon_margin_end"
+ android:layout_marginTop="@dimen/expanding_entry_card_item_icon_margin_top"
+ android:layout_marginBottom="@dimen/expanding_entry_card_item_alternate_icon_margin_bottom" />
+
+</RelativeLayout>
diff --git a/res/layout/expanding_entry_card_view.xml b/res/layout/expanding_entry_card_view.xml
index 8d8583d..b2ff58c 100644
--- a/res/layout/expanding_entry_card_view.xml
+++ b/res/layout/expanding_entry_card_view.xml
@@ -23,7 +23,8 @@
android:lines="1"
android:padding="@dimen/expanding_entry_card_title_padding"
android:singleLine="true"
- android:textSize="@dimen/expanding_entry_card_title_text_size" />
+ android:textSize="@dimen/expanding_entry_card_title_text_size"
+ android:visibility="gone" />
<View
android:layout_width="match_parent"
diff --git a/res/layout/item_group_membership.xml b/res/layout/item_group_membership.xml
index 84d1afe..7f58c2d 100644
--- a/res/layout/item_group_membership.xml
+++ b/res/layout/item_group_membership.xml
@@ -25,7 +25,7 @@
layout="@layout/edit_kind_title" />
<Button
- style="?android:attr/spinnerStyle"
+ style="@style/SpinnerButtonStyle"
android:id="@+id/group_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/layout/quickcontact_content.xml b/res/layout/quickcontact_content.xml
index 74d071c..e98e599 100644
--- a/res/layout/quickcontact_content.xml
+++ b/res/layout/quickcontact_content.xml
@@ -35,6 +35,17 @@
android:background="@drawable/quickcontact_card_border">
<com.android.contacts.quickcontact.ExpandingEntryCardView
style="@style/ExpandingEntryCardStyle"
+ android:id="@+id/no_contact_data_card"
+ android:layout_marginTop="@dimen/communication_card_marginTop"
+ android:visibility="gone" />
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/quickcontact_card_border">
+ <com.android.contacts.quickcontact.ExpandingEntryCardView
+ style="@style/ExpandingEntryCardStyle"
android:id="@+id/communication_card"
android:layout_marginTop="@dimen/communication_card_marginTop"
android:visibility="gone" />
diff --git a/res/layout/quickcontact_header.xml b/res/layout/quickcontact_header.xml
index b71bee0..1f73215 100644
--- a/res/layout/quickcontact_header.xml
+++ b/res/layout/quickcontact_header.xml
@@ -67,7 +67,7 @@
android:textColor="@color/actionbar_text_color"
android:maxLines="@integer/quickcontact_title_lines"
android:ellipsize="end"
- android:layout_gravity="bottom"
+ android:layout_gravity="bottom|start"
android:textSize="@dimen/quickcontact_maximum_title_size"
android:layout_marginStart="@dimen/quickcontact_title_initial_margin"
android:layout_marginEnd="@dimen/quickcontact_title_initial_margin"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index b44f34b..562241e 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -16,6 +16,8 @@
<resources>
<color name="quickcontact_name_detail_background">#66000000</color>
+ <color name="quickcontact_entry_sub_header_text_color">#737373</color>
+ <color name="quickcontact_entry_header_text_color">#202020</color>
<!-- Color of the background of the contact detail and editor pages -->
<color name="background_primary">#f5f5f5</color>
@@ -35,7 +37,6 @@
<color name="action_bar_button_text_color">#FFFFFF</color>
<!-- Color of the selected tab underline (overriding value in ContactsCommon) -->
- <color name="tab_selected_color">#ffeeff41</color>
<color name="contacts_accent_color">#00acc1</color>
<!-- Color of the separator between entries in an ExpandingEntryCardView -->
@@ -61,7 +62,7 @@
<!-- Background color of pinned header items. -->
<color name="list_item_pinned_header_color">#f5f5f5</color>
- <!-- The default color used for tinting photos when no color can be extracted via Palette,
- this is Blue Grey 500 -->
- <color name="quickcontact_default_photo_tint_color">#607D8B</color>
+ <color name="tab_default_color">@color/actionbar_background_color</color>
+ <color name="tab_pressed_color">@color/tab_selected_color</color>
+ <color name="tab_selected_color">#ffeeff41</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0e296fe..877a68f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -167,8 +167,7 @@
<!-- Height of the separator between entries in an ExpandingEntryCardView -->
<dimen name="expanding_entry_card_item_separator_height">1dp</dimen>
<!-- Dimensions for an entry in ExpandingEntryCardView -->
- <dimen name="expanding_entry_card_item_padding_start">67dp</dimen>
- <dimen name="expanding_entry_card_item_padding_with_image_start">20dp</dimen>
+ <dimen name="expanding_entry_card_item_padding_start">20dp</dimen>
<dimen name="expanding_entry_card_item_padding_end">20dp</dimen>
<dimen name="expanding_entry_card_item_padding_top">16dp</dimen>
<dimen name="expanding_entry_card_item_padding_bottom">16dp</dimen>
@@ -184,8 +183,15 @@
<dimen name="expanding_entry_card_item_sub_header_icon_margin_right">4dp</dimen>
<dimen name="expanding_entry_card_item_sub_header_icon_margin_bottom">14dp</dimen>
+ <dimen name="expanding_entry_card_item_icon_margin_top">8dp</dimen>
+ <dimen name="expanding_entry_card_item_alternate_icon_margin_end">0dp</dimen>
+ <dimen name="expanding_entry_card_item_alternate_icon_margin_bottom">10dp</dimen>
+
<dimen name="people_activity_card_elevation">2dp</dimen>
<dimen name="expanding_entry_card_item_icon_height">24dp</dimen>
<dimen name="expanding_entry_card_item_icon_width">24dp</dimen>
+
+ <!-- Width of the box around a tab when the tab has focus -->
+ <dimen name="tab_focused_stroke_width">1dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0683190..494e115 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -651,9 +651,6 @@
<!-- Button Label to see all on an ExpandingEntryCardView [CHAR LIMIT=40] -->
<string name="expanding_entry_card_view_see_all">See all</string>
- <!-- Title of communication card. [CHAR LIMIT=60] -->
- <string name="communication_card_title">Contact</string>
-
<!-- Title of recent card. [CHAR LIMIT=60] -->
<string name="recent_card_title">Recent</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 57c9358..a1a01d1 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -278,4 +278,10 @@
<item name="android:layout_height">wrap_content</item>
</style>
+ <style name="SpinnerButtonStyle" parent="@android:style/Widget.Material.Spinner">
+ <!-- When applying the spinner style to a Button we need to disable the shadow animation
+ on the button since the spinner background is transparent. Otherwise the spinner-button
+ will look ridiculous. -->
+ <item name="android:stateListAnimator">@null</item>
+ </style>
</resources>
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index 2b2f032..633185b 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -24,11 +24,13 @@
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.ColorFilter;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -60,16 +62,24 @@
private final String mText;
private final Drawable mTextIcon;
private final Intent mIntent;
+ private final Drawable mAlternateIcon;
+ private final Intent mAlternateIntent;
+ private final String mAlternateContentDescription;
+ private final boolean mShouldApplyColor;
private final boolean mIsEditable;
public Entry(int viewId, Drawable icon, String header, String subHeader, String text,
- Intent intent, boolean isEditable) {
- this(viewId, icon, header, subHeader, null, text, null, intent, isEditable);
+ Intent intent, Drawable alternateIcon, Intent alternateIntent,
+ String alternateContentDescription, boolean shouldApplyColor,
+ boolean isEditable) {
+ this(viewId, icon, header, subHeader, null, text, null, intent, alternateIcon,
+ alternateIntent, alternateContentDescription, shouldApplyColor, isEditable);
}
public Entry(int viewId, Drawable mainIcon, String header, String subHeader,
Drawable subHeaderIcon, String text, Drawable textIcon, Intent intent,
- boolean isEditable) {
+ Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
+ boolean shouldApplyColor, boolean isEditable) {
mViewId = viewId;
mIcon = mainIcon;
mHeader = header;
@@ -78,6 +88,10 @@
mText = text;
mTextIcon = textIcon;
mIntent = intent;
+ mAlternateIcon = alternateIcon;
+ mAlternateIntent = alternateIntent;
+ mAlternateContentDescription = alternateContentDescription;
+ mShouldApplyColor = shouldApplyColor;
mIsEditable = isEditable;
}
@@ -109,6 +123,22 @@
return mIntent;
}
+ Drawable getAlternateIcon() {
+ return mAlternateIcon;
+ }
+
+ Intent getAlternateIntent() {
+ return mAlternateIntent;
+ }
+
+ String getAlternateContentDescription() {
+ return mAlternateContentDescription;
+ }
+
+ boolean shouldApplyColor() {
+ return mShouldApplyColor;
+ }
+
boolean isEditable() {
return mIsEditable;
}
@@ -187,6 +217,8 @@
mIsExpanded = isExpanded;
mEntryViews = new ArrayList<List<View>>(entries.size());
mEntries = entries;
+ mNumEntries = 0;
+ mAllEntriesInflated = false;
for (List<Entry> entryList : mEntries) {
mNumEntries += entryList.size();
mEntryViews.add(new ArrayList<View>());
@@ -270,16 +302,23 @@
Resources resources = getResources();
layoutParams.height = resources.getDimensionPixelSize(
R.dimen.expanding_entry_card_item_separator_height);
+ // The separator is aligned with the text in the entry. This is offset by a default
+ // margin. If there is an icon present, the icon's width and margin are added
+ int marginStart = resources.getDimensionPixelSize(
+ R.dimen.expanding_entry_card_item_padding_start);
+ ImageView entryIcon = (ImageView) entry.findViewById(R.id.icon);
+ if (entryIcon.getDrawable() != null) {
+ int imageWidthAndMargin =
+ resources.getDimensionPixelSize(
+ R.dimen.expanding_entry_card_item_icon_width) +
+ resources.getDimensionPixelSize(
+ R.dimen.expanding_entry_card_item_image_spacing);
+ marginStart += imageWidthAndMargin;
+ }
if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- layoutParams.rightMargin = resources.getDimensionPixelSize(
- R.dimen.expanding_entry_card_item_padding_start);
- layoutParams.leftMargin = resources.getDimensionPixelSize(
- R.dimen.expanding_entry_card_item_padding_end);
+ layoutParams.rightMargin = marginStart;
} else {
- layoutParams.leftMargin = resources.getDimensionPixelSize(
- R.dimen.expanding_entry_card_item_padding_start);
- layoutParams.rightMargin = resources.getDimensionPixelSize(
- R.dimen.expanding_entry_card_item_padding_end);
+ layoutParams.leftMargin = marginStart;
}
separator.setLayoutParams(layoutParams);
mEntriesViewGroup.addView(separator);
@@ -343,6 +382,19 @@
applyColor();
}
+ public void setEntryHeaderColor(int color) {
+ if (mEntries != null) {
+ for (List<View> entryList : mEntryViews) {
+ for (View entryView : entryList) {
+ TextView header = (TextView) entryView.findViewById(R.id.header);
+ if (header != null) {
+ header.setTextColor(color);
+ }
+ }
+ }
+ }
+ }
+
/**
* The ColorFilter is passed in along with the color so that a new one only needs to be created
* once for the entire activity.
@@ -362,9 +414,15 @@
if (mEntries != null) {
for (List<Entry> entryList : mEntries) {
for (Entry entry : entryList) {
- Drawable icon = entry.getIcon();
- if (icon != null) {
- icon.setColorFilter(mThemeColorFilter);
+ if (entry.shouldApplyColor()) {
+ Drawable icon = entry.getIcon();
+ if (icon != null) {
+ icon.setColorFilter(mThemeColorFilter);
+ }
+ }
+ Drawable alternateIcon = entry.getAlternateIcon();
+ if (alternateIcon != null) {
+ alternateIcon.setColorFilter(mThemeColorFilter);
}
}
}
@@ -379,47 +437,47 @@
// TODO add accessibility content descriptions
private View createEntryView(LayoutInflater layoutInflater, Entry entry) {
- View view = layoutInflater.inflate(
+ final View view = layoutInflater.inflate(
R.layout.expanding_entry_card_item, this, false);
view.setId(entry.getViewId());
- ImageView icon = (ImageView) view.findViewById(R.id.icon);
+ final ImageView icon = (ImageView) view.findViewById(R.id.icon);
if (entry.getIcon() != null) {
icon.setImageDrawable(entry.getIcon());
} else {
icon.setVisibility(View.GONE);
}
- TextView header = (TextView) view.findViewById(R.id.header);
+ final TextView header = (TextView) view.findViewById(R.id.header);
if (entry.getHeader() != null) {
header.setText(entry.getHeader());
} else {
header.setVisibility(View.GONE);
}
- TextView subHeader = (TextView) view.findViewById(R.id.sub_header);
+ final TextView subHeader = (TextView) view.findViewById(R.id.sub_header);
if (entry.getSubHeader() != null) {
subHeader.setText(entry.getSubHeader());
} else {
subHeader.setVisibility(View.GONE);
}
- ImageView subHeaderIcon = (ImageView) view.findViewById(R.id.icon_sub_header);
+ final ImageView subHeaderIcon = (ImageView) view.findViewById(R.id.icon_sub_header);
if (entry.getSubHeaderIcon() != null) {
subHeaderIcon.setImageDrawable(entry.getSubHeaderIcon());
} else {
subHeaderIcon.setVisibility(View.GONE);
}
- TextView text = (TextView) view.findViewById(R.id.text);
+ final TextView text = (TextView) view.findViewById(R.id.text);
if (entry.getText() != null) {
text.setText(entry.getText());
} else {
text.setVisibility(View.GONE);
}
- ImageView textIcon = (ImageView) view.findViewById(R.id.icon_text);
+ final ImageView textIcon = (ImageView) view.findViewById(R.id.icon_text);
if (entry.getTextIcon() != null) {
textIcon.setImageDrawable(entry.getTextIcon());
} else {
@@ -431,6 +489,39 @@
view.setTag(entry.getIntent());
}
+ final ImageView alternateIcon = (ImageView) view.findViewById(R.id.icon_alternate);
+ if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) {
+ alternateIcon.setImageDrawable(entry.getAlternateIcon());
+ alternateIcon.setOnClickListener(mOnClickListener);
+ alternateIcon.setTag(entry.getAlternateIntent());
+ alternateIcon.setId(entry.getViewId());
+ alternateIcon.setVisibility(View.VISIBLE);
+ alternateIcon.setContentDescription(entry.getAlternateContentDescription());
+
+ // Expand the clickable area for alternate icon to be top to bottom and to right edge
+ // of the entry view
+ view.post(new Runnable() {
+ @Override
+ public void run() {
+ final Rect entryRect = new Rect();
+ view.getHitRect(entryRect);
+
+ final Rect alternateIconRect = new Rect();
+ alternateIcon.getHitRect(alternateIconRect);
+ alternateIconRect.bottom = entryRect.bottom;
+ alternateIconRect.top = entryRect.top;
+ if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ alternateIconRect.left = entryRect.left;
+ } else {
+ alternateIconRect.right = entryRect.right;
+ }
+ final TouchDelegate touchDelegate =
+ new TouchDelegate(alternateIconRect, alternateIcon);
+ view.setTouchDelegate(touchDelegate);
+ }
+ });
+ }
+
return view;
}
@@ -529,16 +620,17 @@
/**
* Sets the title text of this ExpandingEntryCardView.
- * @param title The title to set. A null title will result in an empty string being set.
+ * @param title The title to set. A null title will result in the title being removed.
*/
public void setTitle(String title) {
if (mTitleTextView == null) {
Log.e(TAG, "mTitleTextView is null");
}
if (title == null) {
- mTitleTextView.setText("");
+ mTitleTextView.setVisibility(View.GONE);
}
mTitleTextView.setText(title);
+ mTitleTextView.setVisibility(View.VISIBLE);
}
public boolean shouldShow() {
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 0ef16d9..e453a4b 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -31,6 +31,8 @@
import android.content.ContentValues;
import android.content.Intent;
import android.content.Loader;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
@@ -127,7 +129,6 @@
import com.android.contacts.util.StructuredPostalUtils;
import com.android.contacts.widget.MultiShrinkScroller;
import com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener;
-
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
@@ -162,7 +163,6 @@
private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150;
private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1;
private static final int SCRIM_COLOR = Color.argb(0xB2, 0, 0, 0);
- private static final String SCHEME_SMSTO = "smsto";
private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms";
/** This is the Intent action to install a shortcut in the launcher. */
@@ -188,6 +188,7 @@
private ImageView mPhotoView;
private View mTransparentView;
private ExpandingEntryCardView mContactCard;
+ private ExpandingEntryCardView mNoContactDetailsCard;
private ExpandingEntryCardView mRecentCard;
private ExpandingEntryCardView mAboutCard;
/**
@@ -206,13 +207,10 @@
private AsyncTask<Void, Void, Pair<List<List<DataItem>>, Map<String, List<DataItem>>>>
mEntriesAndActionsTask;
private ColorDrawable mWindowScrim;
+ private MaterialColorMapUtils mMaterialColorMapUtils;
private boolean mIsWaitingForOtherPieceOfExitAnimation;
private boolean mIsExitAnimationInProgress;
private boolean mHasComputedThemeColor;
- private ComponentName mSmsComponent;
-
- private static final int MIN_NUM_CONTACT_ENTRIES_SHOWN = 3;
- private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3;
private Contact mContactData;
private ContactLoader mContactLoader;
@@ -221,22 +219,14 @@
private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter();
/**
- * {@link #LEADING_MIMETYPES} and {@link #TRAILING_MIMETYPES} are used to sort MIME-types.
+ * {@link #LEADING_MIMETYPES} is used to sort MIME-types.
*
* <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog,
* in the order specified here.</p>
- *
- * <p>The ones in {@link #TRAILING_MIMETYPES} appear in the end of the dialog, in the order
- * specified here.</p>
- *
- * <p>The rest go between them, in the order in the array.</p>
*/
private static final List<String> LEADING_MIMETYPES = Lists.newArrayList(
- Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE);
-
- /** See {@link #LEADING_MIMETYPES}. */
- private static final List<String> TRAILING_MIMETYPES = Lists.newArrayList(
- StructuredPostal.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE);
+ Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE,
+ StructuredPostal.CONTENT_ITEM_TYPE);
private static final List<String> ABOUT_CARD_MIMETYPES = Lists.newArrayList(
Event.CONTENT_ITEM_TYPE, GroupMembership.CONTENT_ITEM_TYPE, Identity.CONTENT_ITEM_TYPE,
@@ -267,13 +257,16 @@
/** Id for the background Call Log Loader */
private static final int LOADER_CALL_LOG_ID = 3;
private static final int MAX_CALL_LOG_RETRIEVE = 3;
+ private static final int MIN_NUM_CONTACT_ENTRIES_SHOWN = 3;
+ private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3;
+ private static final int CARD_ENTRY_ID_EDIT_CONTACT = -2;
private static final int[] mRecentLoaderIds = new int[]{
LOADER_SMS_ID,
LOADER_CALENDAR_ID,
LOADER_CALL_LOG_ID};
- private Map<Integer, List<ContactInteraction>> mRecentLoaderResults;
+ private Map<Integer, List<ContactInteraction>> mRecentLoaderResults = new HashMap<>();
private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment";
@@ -282,7 +275,11 @@
public void onClick(View v) {
// Data Id is stored as the entry view id
final int dataId = v.getId();
- Object intentObject = v.getTag();
+ if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) {
+ editContact();
+ return;
+ }
+ final Object intentObject = v.getTag();
if (intentObject == null || !(intentObject instanceof Intent)) {
Log.w(TAG, "Intent tag was not used correctly");
return;
@@ -294,7 +291,7 @@
String usageType = DataUsageFeedback.USAGE_TYPE_CALL;
final String scheme = intent.getData().getScheme();
- if ((scheme != null && scheme.equals(SCHEME_SMSTO)) ||
+ if ((scheme != null && scheme.equals(CallUtil.SCHEME_SMSTO)) ||
(intent.getType() != null && intent.getType().equals(MIMETYPE_SMS))) {
usageType = DataUsageFeedback.USAGE_TYPE_SHORT_TEXT;
}
@@ -436,6 +433,12 @@
}
};
+ /**
+ * Sorts among different mimetypes based off:
+ * 1. Times used
+ * 2. Last time used
+ * 3. Statically defined
+ */
private final Comparator<List<DataItem>> mAmongstMimeTypeDataItemComparator =
new Comparator<List<DataItem>> () {
@Override
@@ -470,14 +473,6 @@
return 1;
}
}
- // Trailing types come last, so flip the returns
- for (String mimeType : TRAILING_MIMETYPES) {
- if (lhsMimeType.equals(mimeType)) {
- return 1;
- } else if (rhsMimeType.equals(mimeType)) {
- return -1;
- }
- }
return 0;
}
};
@@ -497,15 +492,16 @@
setContentView(R.layout.quickcontact_activity);
- mSmsComponent = PhoneCapabilityTester.getSmsComponent(this);
+ mMaterialColorMapUtils = new MaterialColorMapUtils(getResources());
mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card);
+ mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card);
mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card);
mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card);
mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller);
+ mNoContactDetailsCard.setOnClickListener(mEntryClickHandler);
mContactCard.setOnClickListener(mEntryClickHandler);
- mContactCard.setTitle(getResources().getString(R.string.communication_card_title));
mContactCard.setExpandButtonText(
getResources().getString(R.string.expanding_entry_card_view_see_all));
@@ -574,7 +570,8 @@
// header tint before the MultiShrinkScroller has been measured will
// cause incorrect tinting calculations.
if (color != 0) {
- setThemeColor(MaterialColorMapUtils.calculateSecondaryColor(color));
+ setThemeColor(mMaterialColorMapUtils
+ .calculatePrimaryAndSecondaryColor(color));
}
}
});
@@ -583,8 +580,8 @@
Trace.endSection();
}
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_CONTACT_EDITOR_ACTIVITY &&
resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) {
// The contact that we were showing has been deleted.
@@ -629,11 +626,11 @@
} else if (oldLookupUri != mLookupUri) {
// After copying a directory contact, the contact URI changes. Therefore,
// we need to restart the loader and reload the new contact.
- mContactLoader = (ContactLoader) getLoaderManager().restartLoader(
- LOADER_CONTACT_ID, null, mLoaderContactCallbacks);
for (int interactionLoaderId : mRecentLoaderIds) {
getLoaderManager().destroyLoader(interactionLoaderId);
}
+ mContactLoader = (ContactLoader) getLoaderManager().restartLoader(
+ LOADER_CONTACT_ID, null, mLoaderContactCallbacks);
}
NfcHandler.register(this, mLookupUri);
@@ -823,10 +820,60 @@
/* numInitialVisibleEntries = */ 1,
/* isExpanded = */ true,
mExpandingEntryCardViewListener);
+
+ if (contactCardEntries.size() == 0 && aboutCardEntries.size() == 0) {
+ initializeNoContactDetailCard();
+ } else {
+ mNoContactDetailsCard.setVisibility(View.GONE);
+ }
+
+ // If the Recent card is already initialized (all recent data is loaded), show the About
+ // card if it has entries. Otherwise About card visibility will be set in bindRecentData()
+ if (isAllRecentDataLoaded() && aboutCardEntries.size() > 0) {
+ mAboutCard.setVisibility(View.VISIBLE);
+ }
Trace.endSection();
}
/**
+ * Create a card that shows "Add email" and "Add phone number" entries in grey.
+ */
+ private void initializeNoContactDetailCard() {
+ final Drawable phoneIcon = getResources().getDrawable(
+ R.drawable.ic_phone_24dp).mutate();
+ final Entry phonePromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT,
+ phoneIcon, getString(R.string.quickcontact_add_phone_number),
+ /* subHeader = */ null, /* text = */ null, getEditContactIntent(),
+ /* alternateIcon = */ null, /* alternateIntent = */ null,
+ /* alternateContentDescription = */ null, /* shouldApplyColor = */ true,
+ /* isEditable = */ false);
+
+ final Drawable emailIcon = getResources().getDrawable(
+ R.drawable.ic_email_24dp).mutate();
+ final Entry emailPromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT,
+ emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null,
+ /* text = */ null, getEditContactIntent(), /* alternateIcon = */ null,
+ /* alternateIntent = */ null, /* alternateContentDescription = */ null,
+ /* shouldApplyColor = */ true, /* isEditable = */ false);
+
+ final List<List<Entry>> promptEntries = new ArrayList<>();
+ promptEntries.add(new ArrayList<Entry>(1));
+ promptEntries.add(new ArrayList<Entry>(1));
+ promptEntries.get(0).add(phonePromptEntry);
+ promptEntries.get(1).add(emailPromptEntry);
+
+ final int subHeaderTextColor = getResources().getColor(
+ R.color.quickcontact_entry_sub_header_text_color);
+ final PorterDuffColorFilter greyColorFilter =
+ new PorterDuffColorFilter(subHeaderTextColor, PorterDuff.Mode.SRC_ATOP);
+ mNoContactDetailsCard.initialize(promptEntries, 2, /* isExpanded = */ false,
+ mExpandingEntryCardViewListener);
+ mNoContactDetailsCard.setVisibility(View.VISIBLE);
+ mNoContactDetailsCard.setEntryHeaderColor(subHeaderTextColor);
+ mNoContactDetailsCard.setColorAndFilter(subHeaderTextColor, greyColorFilter);
+ }
+
+ /**
* Builds the {@link DataItem}s Map out of the Contact.
* @param data The contact to build the data from.
* @return A pair containing a list of data items sorted within mimetype and sorted
@@ -909,6 +956,10 @@
String text = null;
Drawable textIcon = null;
Intent intent = null;
+ boolean shouldApplyColor = true;
+ Drawable alternateIcon = null;
+ Intent alternateIntent = null;
+ String alternateContentDescription = null;
final boolean isEditable = false;
DataKind kind = dataItem.getDataKind();
@@ -998,6 +1049,10 @@
if (PhoneCapabilityTester.isPhone(this)) {
intent = CallUtil.getCallIntent(phone.getNumber());
}
+ alternateIntent = new Intent(Intent.ACTION_SENDTO,
+ Uri.fromParts(CallUtil.SCHEME_SMSTO, phone.getNumber(), null));
+ alternateIcon = getResources().getDrawable(R.drawable.ic_message_24dp);
+ alternateContentDescription = getResources().getString(R.string.sms_other);
}
} else if (dataItem instanceof EmailDataItem) {
final EmailDataItem email = (EmailDataItem) dataItem;
@@ -1088,6 +1143,7 @@
if (icon != null) {
icon.mutate();
}
+ shouldApplyColor = false;
}
}
}
@@ -1099,6 +1155,18 @@
}
}
+ if (alternateIntent != null) {
+ // Do not set the alternate intent is there are no resolves
+ if (!PhoneCapabilityTester.isIntentRegistered(this, alternateIntent)) {
+ alternateIntent = null;
+ }
+
+ // Attempt to use package manager to find a suitable content description if needed
+ if (TextUtils.isEmpty(alternateContentDescription)) {
+ alternateContentDescription = getIntentResolveLabel(alternateIntent);
+ }
+ }
+
// If the Entry has no visual elements, return null
if (icon == null && TextUtils.isEmpty(header) && TextUtils.isEmpty(subHeader) &&
subHeaderIcon == null && TextUtils.isEmpty(text) && textIcon == null) {
@@ -1108,8 +1176,9 @@
final int dataId = dataItem.getId() > Integer.MAX_VALUE ?
-1 : (int) dataItem.getId();
- return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon,
- intent, isEditable);
+ return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, intent,
+ alternateIcon, alternateIntent, alternateContentDescription, shouldApplyColor,
+ isEditable);
}
private List<Entry> dataItemsToEntries(List<DataItem> dataItems) {
@@ -1119,30 +1188,30 @@
if (entry != null) {
entries.add(entry);
}
- // TODO merge secondary intents
- if (dataItem instanceof PhoneDataItem) {
- final PhoneDataItem phone = (PhoneDataItem) dataItem;
- Intent smsIntent = null;
- if (mSmsComponent != null) {
- smsIntent = new Intent(Intent.ACTION_SENDTO,
- Uri.fromParts(CallUtil.SCHEME_SMSTO, phone.getNumber(), null));
- smsIntent.setComponent(mSmsComponent);
- }
- final int dataId = dataItem.getId() > Integer.MAX_VALUE ?
- -1 : (int) dataItem.getId();
- entries.add(new Entry(dataId,
- getResources().getDrawable(R.drawable.ic_message_24dp),
- getResources().getString(R.string.send_message),
- /* subHeader = */ null,
- /* text = */ phone.buildDataString(this,
- dataItem.getDataKind()),
- smsIntent,
- /* isEditable = */ false));
- }
}
return entries;
}
+ private String getIntentResolveLabel(Intent intent) {
+ final List<ResolveInfo> matches = getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+
+ // Pick first match, otherwise best found
+ ResolveInfo bestResolve = null;
+ final int size = matches.size();
+ if (size == 1) {
+ bestResolve = matches.get(0);
+ } else if (size > 1) {
+ bestResolve = ResolveCache.getInstance(this).getBestResolve(intent, matches);
+ }
+
+ if (bestResolve == null) {
+ return null;
+ }
+
+ return String.valueOf(bestResolve.loadLabel(getPackageManager()));
+ }
+
/**
* Asynchronously extract the most vibrant color from the PhotoView. Once extracted,
* apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms
@@ -1161,16 +1230,15 @@
final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap();
final int primaryColor = colorFromBitmap(bitmap);
if (primaryColor != 0) {
- return MaterialColorMapUtils.calculatePrimaryAndSecondaryColor(
+ return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(
primaryColor);
}
}
if (imageViewDrawable instanceof LetterTileDrawable) {
final int primaryColor = ((LetterTileDrawable) imageViewDrawable).getColor();
- return MaterialColorMapUtils.calculateSecondaryColor(primaryColor);
+ return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(primaryColor);
}
- return MaterialColorMapUtils.calculatePrimaryAndSecondaryColor(
- getResources().getColor(R.color.quickcontact_default_photo_tint_color));
+ return MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors(getResources());
}
@Override
@@ -1274,6 +1342,10 @@
interaction.getViewFooter(this),
interaction.getFooterIcon(this),
interaction.getIntent(),
+ /* alternateIcon = */ null,
+ /* alternateIntent = */ null,
+ /* alternateContentDescription = */ null,
+ /* shouldApplyColor = */ true,
/* isEditable = */ false));
}
return entries;
@@ -1283,6 +1355,7 @@
new LoaderCallbacks<Contact>() {
@Override
public void onLoaderReset(Loader<Contact> loader) {
+ mContactData = null;
}
@Override
@@ -1388,11 +1461,6 @@
@Override
public void onLoadFinished(Loader<List<ContactInteraction>> loader,
List<ContactInteraction> data) {
- if (mRecentLoaderResults == null) {
- mRecentLoaderResults = new HashMap<Integer, List<ContactInteraction>>();
- }
- Log.v(TAG, "onLoadFinished ~ loader.getId() " + loader.getId() + " data.size() " +
- data.size());
mRecentLoaderResults.put(loader.getId(), data);
if (isAllRecentDataLoaded()) {
@@ -1404,7 +1472,6 @@
public void onLoaderReset(Loader<List<ContactInteraction>> loader) {
mRecentLoaderResults.remove(loader.getId());
}
-
};
private boolean isAllRecentDataLoaded() {
@@ -1465,11 +1532,15 @@
return mContactData != null && !mContactData.isDirectoryEntry();
}
- private void editContact() {
+ private Intent getEditContactIntent() {
final Intent intent = new Intent(Intent.ACTION_EDIT, mLookupUri);
mContactLoader.cacheResult();
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
- startActivityForResult(intent, REQUEST_CODE_CONTACT_EDITOR_ACTIVITY);
+ return intent;
+ }
+
+ private void editContact() {
+ startActivityForResult(getEditContactIntent(), REQUEST_CODE_CONTACT_EDITOR_ACTIVITY);
}
private void toggleStar(MenuItem starredMenuItem) {
diff --git a/src/com/android/contacts/widget/MultiShrinkScroller.java b/src/com/android/contacts/widget/MultiShrinkScroller.java
index d9dac00..23481a7 100644
--- a/src/com/android/contacts/widget/MultiShrinkScroller.java
+++ b/src/com/android/contacts/widget/MultiShrinkScroller.java
@@ -872,8 +872,8 @@
mToolbar.getBoundsOnScreen(largeTextViewRect);
mInvisiblePlaceholderTextView.getBoundsOnScreen(invisiblePlaceholderTextViewRect);
if (isLayoutRtl()) {
- mCollapsedTitleStartMargin = invisiblePlaceholderTextViewRect.right
- - largeTextViewRect.right;
+ mCollapsedTitleStartMargin = largeTextViewRect.right
+ - invisiblePlaceholderTextViewRect.right;
} else {
mCollapsedTitleStartMargin = invisiblePlaceholderTextViewRect.left
- largeTextViewRect.left;