Adds VOLTE icon and capabilities to QuickContact
bug: 16015752
Change-Id: I9970d5901f80fc56d7528d61da6b4e8b8c66e0c1
diff --git a/res/layout/expanding_entry_card_item.xml b/res/layout/expanding_entry_card_item.xml
index 4710df2..567c02c 100644
--- a/res/layout/expanding_entry_card_item.xml
+++ b/res/layout/expanding_entry_card_item.xml
@@ -82,16 +82,28 @@
android:layout_marginTop="@dimen/expanding_entry_card_item_text_icon_margin_top"
android:layout_marginEnd="@dimen/expanding_entry_card_item_text_icon_margin_right" />
- <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:background="?android:attr/selectableItemBackgroundBorderless"
- android:paddingTop="@dimen/expanding_entry_card_item_icon_margin_top"
- android:paddingBottom="@dimen/expanding_entry_card_item_alternate_icon_margin_bottom"
- android:layout_marginStart="@dimen/expanding_entry_card_item_alternate_icon_start_margin" />
+ <ImageView
+ android:id="@+id/icon_alternate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toStartOf="@+id/third_icon"
+ android:layout_alignWithParentIfMissing="true"
+ android:visibility="gone"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:paddingTop="@dimen/expanding_entry_card_item_icon_margin_top"
+ android:paddingBottom="@dimen/expanding_entry_card_item_alternate_icon_margin_bottom"
+ android:layout_marginStart="@dimen/expanding_entry_card_item_alternate_icon_start_margin" />
+ <ImageView
+ android:id="@+id/third_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:visibility="gone"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:paddingTop="@dimen/expanding_entry_card_item_icon_margin_top"
+ android:paddingBottom="@dimen/expanding_entry_card_item_alternate_icon_margin_bottom"
+ android:layout_marginStart="@dimen/expanding_entry_card_item_alternate_icon_start_margin" />
</view>
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index 091971e..b219988 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -35,8 +35,9 @@
import android.util.Log;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
-import android.view.TouchDelegate;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -81,21 +82,26 @@
private final boolean mShouldApplyColor;
private final boolean mIsEditable;
private final EntryContextMenuInfo mEntryContextMenuInfo;
+ private final Drawable mThirdIcon;
+ private final Intent mThirdIntent;
+ private final String mThirdContentDescription;
public Entry(int id, Drawable icon, String header, String subHeader, String text,
Intent intent, Drawable alternateIcon, Intent alternateIntent,
String alternateContentDescription, boolean shouldApplyColor,
- boolean isEditable, EntryContextMenuInfo entryContextMenuInfo) {
+ boolean isEditable, EntryContextMenuInfo entryContextMenuInfo,
+ Drawable thirdIcon, Intent thirdIntent, String thirdContentDescription) {
this(id, icon, header, subHeader, null, text, null, intent, alternateIcon,
alternateIntent, alternateContentDescription, shouldApplyColor, isEditable,
- entryContextMenuInfo);
+ entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
}
public Entry(int id, Drawable mainIcon, String header, String subHeader,
Drawable subHeaderIcon, String text, Drawable textIcon, Intent intent,
Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
boolean shouldApplyColor, boolean isEditable,
- EntryContextMenuInfo entryContextMenuInfo) {
+ EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
+ String thirdContentDescription) {
mId = id;
mIcon = mainIcon;
mHeader = header;
@@ -110,6 +116,9 @@
mShouldApplyColor = shouldApplyColor;
mIsEditable = isEditable;
mEntryContextMenuInfo = entryContextMenuInfo;
+ mThirdIcon = thirdIcon;
+ mThirdIntent = thirdIntent;
+ mThirdContentDescription = thirdContentDescription;
}
Drawable getIcon() {
@@ -167,6 +176,18 @@
EntryContextMenuInfo getEntryContextMenuInfo() {
return mEntryContextMenuInfo;
}
+
+ Drawable getThirdIcon() {
+ return mThirdIcon;
+ }
+
+ Intent getThirdIntent() {
+ return mThirdIntent;
+ }
+
+ String getThirdContentDescription() {
+ return mThirdContentDescription;
+ }
}
public interface ExpandingEntryCardViewListener {
@@ -541,6 +562,10 @@
if (alternateIcon != null) {
alternateIcon.setColorFilter(mThemeColorFilter);
}
+ Drawable thirdIcon = entry.getThirdIcon();
+ if (thirdIcon != null) {
+ thirdIcon.setColorFilter(mThemeColorFilter);
+ }
}
}
}
@@ -621,36 +646,6 @@
header.setLayoutParams(headerLayoutParams);
}
- 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(new EntryTag(entry.getId(), entry.getAlternateIntent()));
- alternateIcon.setVisibility(View.VISIBLE);
- alternateIcon.setContentDescription(entry.getAlternateContentDescription());
-
- // Expand the clickable area for alternate icon to be top to bottom and to end edge
- // of the entry view
- view.post(new Runnable() {
- @Override
- public void run() {
- final Rect alternateIconRect = new Rect();
- alternateIcon.getHitRect(alternateIconRect);
-
- alternateIconRect.bottom = view.getHeight();
- alternateIconRect.top = 0;
- if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- alternateIconRect.left = 0;
- } else {
- alternateIconRect.right = view.getWidth();
- }
- final TouchDelegate touchDelegate =
- new TouchDelegate(alternateIconRect, alternateIcon);
- view.setTouchDelegate(touchDelegate);
- }
- });
- }
-
// Adjust the top padding size for entries with an invisible icon. The padding depends on
// if there is a sub header or text section
if (iconVisibility == View.INVISIBLE &&
@@ -666,6 +661,27 @@
view.getPaddingBottom());
}
+ final ImageView alternateIcon = (ImageView) view.findViewById(R.id.icon_alternate);
+ final ImageView thirdIcon = (ImageView) view.findViewById(R.id.third_icon);
+
+ if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) {
+ alternateIcon.setImageDrawable(entry.getAlternateIcon());
+ alternateIcon.setOnClickListener(mOnClickListener);
+ alternateIcon.setTag(new EntryTag(entry.getId(), entry.getAlternateIntent()));
+ alternateIcon.setVisibility(View.VISIBLE);
+ alternateIcon.setContentDescription(entry.getAlternateContentDescription());
+ }
+
+ if (entry.getThirdIcon() != null && entry.getThirdIntent() != null) {
+ thirdIcon.setImageDrawable(entry.getThirdIcon());
+ thirdIcon.setOnClickListener(mOnClickListener);
+ thirdIcon.setTag(new EntryTag(entry.getId(), entry.getThirdIntent()));
+ thirdIcon.setVisibility(View.VISIBLE);
+ thirdIcon.setContentDescription(entry.getThirdContentDescription());
+ }
+
+ // Set a custom touch listener for expanding the extra icon touch areas
+ view.setOnTouchListener(new EntryTouchListener(view, alternateIcon, thirdIcon));
view.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
return view;
@@ -920,4 +936,103 @@
return mIntent;
}
}
+
+ /**
+ * This custom touch listener increases the touch area for the second and third icons, if
+ * they are present. This is necessary to maintain other properties on an entry view, like
+ * using a top padding on entry. Based off of {@link android.view.TouchDelegate}
+ */
+ private static final class EntryTouchListener implements View.OnTouchListener {
+ private final View mEntry;
+ private final ImageView mAlternateIcon;
+ private final ImageView mThirdIcon;
+ /** mTouchedView locks in a view on touch down */
+ private View mTouchedView;
+ /** mSlop adds some space to account for touches that are just outside the hit area */
+ private int mSlop;
+
+ public EntryTouchListener(View entry, ImageView alternateIcon, ImageView thirdIcon) {
+ mEntry = entry;
+ mAlternateIcon = alternateIcon;
+ mThirdIcon = thirdIcon;
+ mSlop = ViewConfiguration.get(entry.getContext()).getScaledTouchSlop();
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ View touchedView = mTouchedView;
+ boolean sendToTouched = false;
+ boolean hit = true;
+ boolean handled = false;
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ if (hitThirdIcon(event)) {
+ mTouchedView = mThirdIcon;
+ sendToTouched = true;
+ } else if (hitAlternateIcon(event)) {
+ mTouchedView = mAlternateIcon;
+ sendToTouched = true;
+ } else {
+ mTouchedView = mEntry;
+ sendToTouched = false;
+ }
+ touchedView = mTouchedView;
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_MOVE:
+ sendToTouched = mTouchedView != null && mTouchedView != mEntry;
+ if (sendToTouched) {
+ final Rect slopBounds = new Rect();
+ touchedView.getHitRect(slopBounds);
+ slopBounds.inset(-mSlop, -mSlop);
+ if (!slopBounds.contains((int) event.getX(), (int) event.getY())) {
+ hit = false;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ sendToTouched = mTouchedView != null && mTouchedView != mEntry;
+ mTouchedView = null;
+ break;
+ }
+ if (sendToTouched) {
+ if (hit) {
+ event.setLocation(touchedView.getWidth() / 2, touchedView.getHeight() / 2);
+ } else {
+ // Offset event coordinates to be outside the target view (in case it does
+ // something like tracking pressed state)
+ event.setLocation(-(mSlop * 2), -(mSlop * 2));
+ }
+ handled = touchedView.dispatchTouchEvent(event);
+ }
+ return handled;
+ }
+
+ private boolean hitThirdIcon(MotionEvent event) {
+ if (mEntry.isLayoutRtl()) {
+ return mThirdIcon.getVisibility() == View.VISIBLE &&
+ event.getX() < mThirdIcon.getRight();
+ } else {
+ return mThirdIcon.getVisibility() == View.VISIBLE &&
+ event.getX() > mThirdIcon.getLeft();
+ }
+ }
+
+ /**
+ * Should be used after checking if third icon was hit
+ */
+ private boolean hitAlternateIcon(MotionEvent event) {
+ // LayoutParams used to add the start margin to the touch area
+ final RelativeLayout.LayoutParams alternateIconParams =
+ (RelativeLayout.LayoutParams) mAlternateIcon.getLayoutParams();
+ if (mEntry.isLayoutRtl()) {
+ return mAlternateIcon.getVisibility() == View.VISIBLE &&
+ event.getX() < mAlternateIcon.getRight() + alternateIconParams.rightMargin;
+ } else {
+ return mAlternateIcon.getVisibility() == View.VISIBLE &&
+ event.getX() > mAlternateIcon.getLeft() - alternateIconParams.leftMargin;
+ }
+ }
+ }
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 50e4ff7..5964aeb 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -135,7 +135,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;
@@ -185,6 +184,8 @@
private static final String MIMETYPE_HANGOUTS =
"vnd.android.cursor.item/vnd.googleplus.profile.comm";
private static final String INTENT_DATA_HANGOUTS_VIDEO = "Start video call";
+ private static final String CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY =
+ "com.android.contacts.quickcontact.QuickContactActivity";
/**
* The URI used to load the the Contact. Once the contact is loaded, use Contact#getLookupUri()
@@ -937,7 +938,10 @@
/* shouldApplyColor = */ false,
/* isEditable = */ false,
/* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName,
- getResources().getString(R.string.name_phonetic)));
+ getResources().getString(R.string.name_phonetic)),
+ /* thirdIcon = */ null,
+ /* thirdIntent = */ null,
+ /* thirdContentDescription = */ null);
List<Entry> phoneticList = new ArrayList<>();
phoneticList.add(phoneticEntry);
// Phonetic name comes after nickname. Check to see if the first entry type is nickname
@@ -987,7 +991,9 @@
/* subHeader = */ null, /* text = */ null, getEditContactIntent(),
/* alternateIcon = */ null, /* alternateIntent = */ null,
/* alternateContentDescription = */ null, /* shouldApplyColor = */ true,
- /* isEditable = */ false, /* EntryContextMenuInfo = */ null);
+ /* isEditable = */ false, /* EntryContextMenuInfo = */ null,
+ /* thirdIcon = */ null, /* thirdIntent = */ null,
+ /* thirdContentDescription = */ null);
final Drawable emailIcon = getResources().getDrawable(
R.drawable.ic_email_24dp).mutate();
@@ -996,7 +1002,8 @@
/* text = */ null, getEditContactIntent(), /* alternateIcon = */ null,
/* alternateIntent = */ null, /* alternateContentDescription = */ null,
/* shouldApplyColor = */ true, /* isEditable = */ false,
- /* EntryContextMenuInfo = */ null);
+ /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null,
+ /* thirdIntent = */ null, /* thirdContentDescription = */ null);
final List<List<Entry>> promptEntries = new ArrayList<>();
promptEntries.add(new ArrayList<Entry>(1));
@@ -1157,6 +1164,9 @@
String alternateContentDescription = null;
final boolean isEditable = false;
EntryContextMenuInfo entryContextMenuInfo = null;
+ Drawable thirdIcon = null;
+ Intent thirdIntent = null;
+ String thirdContentDescription = null;
context = context.getApplicationContext();
DataKind kind = dataItem.getDataKind();
@@ -1273,8 +1283,18 @@
}
alternateIntent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts(CallUtil.SCHEME_SMSTO, phone.getNumber(), null));
+
alternateIcon = context.getResources().getDrawable(R.drawable.ic_message_24dp);
alternateContentDescription = context.getResources().getString(R.string.sms_other);
+
+ // Add video call button if supported
+ if (CallUtil.isVideoEnabled()) {
+ thirdIcon = context.getResources().getDrawable(R.drawable.ic_videocam);
+ thirdIntent = CallUtil.getVideoCallIntent(phone.getNumber(),
+ CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY);
+ thirdContentDescription =
+ context.getResources().getString(R.string.description_video_call);
+ }
}
} else if (dataItem instanceof EmailDataItem) {
final EmailDataItem email = (EmailDataItem) dataItem;
@@ -1406,7 +1426,7 @@
return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, intent,
alternateIcon, alternateIntent, alternateContentDescription, shouldApplyColor,
- isEditable, entryContextMenuInfo);
+ isEditable, entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
}
private List<Entry> dataItemsToEntries(List<DataItem> dataItems,
@@ -1574,7 +1594,10 @@
/* alternateContentDescription = */ null,
/* shouldApplyColor = */ true,
/* isEditable = */ false,
- /* EntryContextMenuInfo = */ null));
+ /* EntryContextMenuInfo = */ null,
+ /* thirdIcon = */ null,
+ /* thirdIntent = */ null,
+ /* thirdContentDescription = */ null));
}
return entries;
}