Merge "Change the column number from 2 to 3 in Portrait favorites on Volantis" into lmp-dev
diff --git a/res/layout/expanding_entry_card_item.xml b/res/layout/expanding_entry_card_item.xml
index 16571a7..138a3a5 100644
--- a/res/layout/expanding_entry_card_item.xml
+++ b/res/layout/expanding_entry_card_item.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<RelativeLayout
+<view
+ class="com.android.contacts.quickcontact.ExpandingEntryCardView$EntryView"
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/SelectableItem"
android:layout_width="match_parent"
@@ -93,4 +94,4 @@
android:layout_marginTop="@dimen/expanding_entry_card_item_icon_margin_top"
android:layout_marginBottom="@dimen/expanding_entry_card_item_alternate_icon_margin_bottom" />
-</RelativeLayout>
+</view>
diff --git a/res/layout/people_activity_toolbar.xml b/res/layout/people_activity_toolbar.xml
index fe5be04..e69728b 100644
--- a/res/layout/people_activity_toolbar.xml
+++ b/res/layout/people_activity_toolbar.xml
@@ -14,14 +14,10 @@
limitations under the License.
-->
-<!-- Need to set a non null background on Toolbar in order for MenuItem ripples to be drawn on
- this view, instead of another. This will *not* cause an additional draw since the
- background is transparent.-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar_parent"
android:orientation="vertical"
android:layout_width="match_parent"
- android:background="#00000000"
android:elevation="@dimen/tab_elevation"
android:layout_height="wrap_content" >
diff --git a/res/layout/quickcontact_activity.xml b/res/layout/quickcontact_activity.xml
index 577a451..6d94fcc 100644
--- a/res/layout/quickcontact_activity.xml
+++ b/res/layout/quickcontact_activity.xml
@@ -35,12 +35,9 @@
android:contentDescription="@string/quickcontact_transparent_view_description"
android:id="@+id/transparent_view" />
- <!-- Needs a non null background for elevation to work on this View. This will *not*
- cause an additional draw since the background is transparent. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#00000000"
android:id="@+id/toolbar_parent">
<include layout="@layout/quickcontact_header" />
</FrameLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8f6e022..84ecea0 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -24,18 +24,17 @@
<color name="background_social_updates">#ffeeeeee</color>
- <!-- Color of the background of the action bar -->
- <color name="action_bar_background">#e6e6e6</color>
-
- <!-- Color used for system bar and navigation bar. -->
- <color name="primary_dark">#008aa1</color>
-
- <!-- Color of the background of the action bar when highlighted (ie. pressed, focused) -->
+ <!-- TODO: remove these colors once we delete the group code (b/16522929) -->
+ <color name="action_bar_background">#0288d1</color>
<color name="action_bar_background_highlight">#cecece</color>
-
- <!-- Color of the text for buttons in the action bar -->
<color name="action_bar_button_text_color">#FFFFFF</color>
+ <color name="actionbar_background_color">@color/primary_color</color>
+ <color name="actionbar_background_color_dark">@color/primary_color_dark</color>
+
+ <color name="primary_color_dark">#0277bd</color>
+ <color name="primary_color">#0288d1</color>
+
<!-- Color of the selected tab underline (overriding value in ContactsCommon) -->
<color name="contacts_accent_color">#00acc1</color>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 37d0c94..12fafbc 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -64,8 +64,8 @@
<item name="android:icon">@android:color/transparent</item>
<item name="android:listViewStyle">@style/ListViewStyle</item>
<item name="android:windowBackground">@color/background_primary</item>
- <item name="android:colorPrimaryDark">@color/primary_dark</item>
- <item name="android:colorPrimary">@color/actionbar_background_color</item>
+ <item name="android:colorPrimaryDark">@color/primary_color_dark</item>
+ <item name="android:colorPrimary">@color/primary_color</item>
<item name="list_item_height">?android:attr/listPreferredItemHeight</item>
<item name="activated_background">@drawable/list_item_activated_background</item>
<item name="section_header_background">@drawable/list_title_holo</item>
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 363e459..75f3607 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -359,6 +359,9 @@
portraitViewPagerTabs, landscapeViewPagerTabs, toolbar);
mActionBarAdapter.initialize(savedState, mRequest);
+ // Add shadow under toolbar
+ ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
+
// Configure action button
final View floatingActionButtonContainer = findViewById(
R.id.floating_action_button_container);
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index 49a2b85..a536f8c 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -33,9 +33,11 @@
import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.TouchDelegate;
import android.view.View;
+import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -78,19 +80,22 @@
private final String mAlternateContentDescription;
private final boolean mShouldApplyColor;
private final boolean mIsEditable;
+ private final EntryContextMenuInfo mEntryContextMenuInfo;
public Entry(int viewId, Drawable icon, String header, String subHeader, String text,
Intent intent, Drawable alternateIcon, Intent alternateIntent,
String alternateContentDescription, boolean shouldApplyColor,
- boolean isEditable) {
+ boolean isEditable, EntryContextMenuInfo entryContextMenuInfo) {
this(viewId, icon, header, subHeader, null, text, null, intent, alternateIcon,
- alternateIntent, alternateContentDescription, shouldApplyColor, isEditable);
+ alternateIntent, alternateContentDescription, shouldApplyColor, isEditable,
+ entryContextMenuInfo);
}
public Entry(int viewId, Drawable mainIcon, String header, String subHeader,
Drawable subHeaderIcon, String text, Drawable textIcon, Intent intent,
Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
- boolean shouldApplyColor, boolean isEditable) {
+ boolean shouldApplyColor, boolean isEditable,
+ EntryContextMenuInfo entryContextMenuInfo) {
mViewId = viewId;
mIcon = mainIcon;
mHeader = header;
@@ -104,6 +109,7 @@
mAlternateContentDescription = alternateContentDescription;
mShouldApplyColor = shouldApplyColor;
mIsEditable = isEditable;
+ mEntryContextMenuInfo = entryContextMenuInfo;
}
Drawable getIcon() {
@@ -157,6 +163,10 @@
int getViewId() {
return mViewId;
}
+
+ EntryContextMenuInfo getEntryContextMenuInfo() {
+ return mEntryContextMenuInfo;
+ }
}
public interface ExpandingEntryCardViewListener {
@@ -170,6 +180,7 @@
private CharSequence mExpandButtonText;
private CharSequence mCollapseButtonText;
private OnClickListener mOnClickListener;
+ private OnCreateContextMenuListener mOnCreateContextMenuListener;
private boolean mIsExpanded = false;
private int mCollapsedEntriesCount;
private ExpandingEntryCardViewListener mListener;
@@ -292,6 +303,11 @@
mOnClickListener = listener;
}
+ @Override
+ public void setOnCreateContextMenuListener (OnCreateContextMenuListener listener) {
+ mOnCreateContextMenuListener = listener;
+ }
+
private void insertEntriesIntoViewGroup() {
mEntriesViewGroup.removeAllViews();
@@ -469,10 +485,12 @@
}
}
- private View createEntryView(LayoutInflater layoutInflater, Entry entry, int iconVisibility) {
- final View view = layoutInflater.inflate(
+ private View createEntryView(LayoutInflater layoutInflater, final Entry entry,
+ int iconVisibility) {
+ final EntryView view = (EntryView) layoutInflater.inflate(
R.layout.expanding_entry_card_item, this, false);
+ view.setContextMenuInfo(entry.getEntryContextMenuInfo());
view.setId(entry.getViewId());
final ImageView icon = (ImageView) view.findViewById(R.id.icon);
@@ -570,6 +588,9 @@
view.getPaddingBottom());
}
+
+ view.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
+
return view;
}
@@ -748,4 +769,43 @@
public boolean shouldShow() {
return mEntries != null && mEntries.size() > 0;
}
+
+ public static final class EntryView extends RelativeLayout {
+ private EntryContextMenuInfo mEntryContextMenuInfo;
+
+ public EntryView(Context context) {
+ super(context);
+ }
+
+ public EntryView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setContextMenuInfo(EntryContextMenuInfo info) {
+ mEntryContextMenuInfo = info;
+ }
+
+ @Override
+ protected ContextMenuInfo getContextMenuInfo() {
+ return mEntryContextMenuInfo;
+ }
+ }
+
+ public static final class EntryContextMenuInfo implements ContextMenuInfo {
+ private final String mCopyText;
+ private final String mCopyLabel;
+
+ public EntryContextMenuInfo(String copyText, String copyLabel) {
+ mCopyText = copyText;
+ mCopyLabel = copyLabel;
+ }
+
+ public String getCopyText() {
+ return mCopyText;
+ }
+
+ public String getCopyLabel() {
+ return mCopyLabel;
+ }
+ }
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index a49293c..f5d4951 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -70,11 +70,14 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.View.OnCreateContextMenuListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -86,6 +89,7 @@
import com.android.contacts.NfcHandler;
import com.android.contacts.R;
import com.android.contacts.common.CallUtil;
+import com.android.contacts.common.ClipboardUtils;
import com.android.contacts.common.Collapser;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.editor.SelectAccountDialogFragment;
@@ -115,6 +119,7 @@
import com.android.contacts.common.util.DateUtils;
import com.android.contacts.common.util.MaterialColorMapUtils;
import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
+import com.android.contacts.common.util.ViewUtil;
import com.android.contacts.detail.ContactDisplayUtils;
import com.android.contacts.interactions.CalendarInteractionsLoader;
import com.android.contacts.interactions.CallLogInteractionsLoader;
@@ -122,6 +127,7 @@
import com.android.contacts.interactions.ContactInteraction;
import com.android.contacts.interactions.SmsInteractionsLoader;
import com.android.contacts.quickcontact.ExpandingEntryCardView.Entry;
+import com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo;
import com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener;
import com.android.contacts.util.ImageViewDrawableSetter;
import com.android.contacts.util.PhoneCapabilityTester;
@@ -337,6 +343,33 @@
}
};
+ private final OnCreateContextMenuListener mEntryContextMenuListener =
+ new OnCreateContextMenuListener() {
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ if (menuInfo == null) {
+ return;
+ }
+ EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo;
+ menu.setHeaderTitle(info.getCopyText());
+ menu.add(R.string.copy_text);
+ }
+ };
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ EntryContextMenuInfo menuInfo;
+ try {
+ menuInfo = (EntryContextMenuInfo) item.getMenuInfo();
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return false;
+ }
+
+ ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(), true);
+ return true;
+ }
+
/**
* Headless fragment used to handle account selection callbacks invoked from
* {@link DirectoryContactUtil}.
@@ -519,11 +552,13 @@
mContactCard.setOnClickListener(mEntryClickHandler);
mContactCard.setExpandButtonText(
getResources().getString(R.string.expanding_entry_card_view_see_all));
+ mContactCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
mRecentCard.setOnClickListener(mEntryClickHandler);
mRecentCard.setTitle(getResources().getString(R.string.recent_card_title));
mAboutCard.setOnClickListener(mEntryClickHandler);
+ mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
mPhotoView = (ImageView) findViewById(R.id.photo);
mTransparentView = findViewById(R.id.transparent_view);
@@ -536,6 +571,9 @@
});
}
+ // Allow a shadow to be shown under the toolbar.
+ ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
+
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setActionBar(toolbar);
getActionBar().setTitle(null);
@@ -859,12 +897,13 @@
/* alternateIntent = */ null,
/* alternateContentDescription = */ null,
/* shouldApplyColor = */ false,
- /* isEditable = */ false
- );
+ /* isEditable = */ false,
+ /* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName,
+ getResources().getString(R.string.name_phonetic)));
List<Entry> phoneticList = new ArrayList<>();
phoneticList.add(phoneticEntry);
// Phonetic name comes after nickname. Check to see if the first entry type is nickname
- if (aboutCardEntries.get(0).get(0).getHeader().equals(
+ if (aboutCardEntries.size() > 0 && aboutCardEntries.get(0).get(0).getHeader().equals(
getResources().getString(R.string.header_nickname_entry))) {
aboutCardEntries.add(1, phoneticList);
} else {
@@ -904,7 +943,7 @@
/* subHeader = */ null, /* text = */ null, getEditContactIntent(),
/* alternateIcon = */ null, /* alternateIntent = */ null,
/* alternateContentDescription = */ null, /* shouldApplyColor = */ true,
- /* isEditable = */ false);
+ /* isEditable = */ false, /* EntryContextMenuInfo = */ null);
final Drawable emailIcon = getResources().getDrawable(
R.drawable.ic_email_24dp).mutate();
@@ -912,7 +951,8 @@
emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null,
/* text = */ null, getEditContactIntent(), /* alternateIcon = */ null,
/* alternateIntent = */ null, /* alternateContentDescription = */ null,
- /* shouldApplyColor = */ true, /* isEditable = */ false);
+ /* shouldApplyColor = */ true, /* isEditable = */ false,
+ /* EntryContextMenuInfo = */ null);
final List<List<Entry>> promptEntries = new ArrayList<>();
promptEntries.add(new ArrayList<Entry>(1));
@@ -1019,6 +1059,7 @@
Intent alternateIntent = null;
String alternateContentDescription = null;
final boolean isEditable = false;
+ EntryContextMenuInfo entryContextMenuInfo = null;
DataKind kind = dataItem.getDataKind();
@@ -1044,10 +1085,12 @@
im.getCustomProtocol()).toString();
subHeader = im.getData();
}
+ entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header);
} else if (dataItem instanceof OrganizationDataItem) {
final OrganizationDataItem organization = (OrganizationDataItem) dataItem;
header = getResources().getString(R.string.header_organization_entry);
subHeader = organization.getCompany();
+ entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
text = organization.getTitle();
} else if (dataItem instanceof NicknameDataItem) {
final NicknameDataItem nickname = (NicknameDataItem) dataItem;
@@ -1062,15 +1105,18 @@
if (!duplicatesTitle) {
header = getResources().getString(R.string.header_nickname_entry);
subHeader = nickname.getName();
+ entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
}
} else if (dataItem instanceof NoteDataItem) {
final NoteDataItem note = (NoteDataItem) dataItem;
header = getResources().getString(R.string.header_note_entry);
subHeader = note.getNote();
+ entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
} else if (dataItem instanceof WebsiteDataItem) {
final WebsiteDataItem website = (WebsiteDataItem) dataItem;
header = getResources().getString(R.string.header_website_entry);
subHeader = website.getUrl();
+ entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
try {
final WebAddress webAddress = new WebAddress(website.buildDataString(this, kind));
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
@@ -1105,6 +1151,7 @@
}
header = getResources().getString(R.string.header_relation_entry);
subHeader = relation.getName();
+ entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
if (relation.hasKindTypeColumn(kind)) {
text = Relation.getTypeLabel(getResources(), relation.getKindTypeColumn(kind),
relation.getLabel()).toString();
@@ -1113,6 +1160,8 @@
final PhoneDataItem phone = (PhoneDataItem) dataItem;
if (!TextUtils.isEmpty(phone.getNumber())) {
header = phone.buildDataString(this, kind);
+ entryContextMenuInfo = new EntryContextMenuInfo(header,
+ getResources().getString(R.string.phoneLabelsGroup));
if (phone.hasKindTypeColumn(kind)) {
text = Phone.getTypeLabel(getResources(), phone.getKindTypeColumn(kind),
phone.getLabel()).toString();
@@ -1133,6 +1182,8 @@
final Uri mailUri = Uri.fromParts(CallUtil.SCHEME_MAILTO, address, null);
intent = new Intent(Intent.ACTION_SENDTO, mailUri);
header = email.getAddress();
+ entryContextMenuInfo = new EntryContextMenuInfo(header,
+ getResources().getString(R.string.emailLabelsGroup));
if (email.hasKindTypeColumn(kind)) {
text = Email.getTypeLabel(getResources(), email.getKindTypeColumn(kind),
email.getLabel()).toString();
@@ -1145,6 +1196,8 @@
if (!TextUtils.isEmpty(postalAddress)) {
intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
header = postal.getFormattedAddress();
+ entryContextMenuInfo = new EntryContextMenuInfo(header,
+ getResources().getString(R.string.postalLabelsGroup));
if (postal.hasKindTypeColumn(kind)) {
text = StructuredPostal.getTypeLabel(getResources(),
postal.getKindTypeColumn(kind), postal.getLabel()).toString();
@@ -1162,6 +1215,8 @@
final Uri callUri = Uri.fromParts(CallUtil.SCHEME_SIP, address, null);
intent = CallUtil.getCallIntent(callUri);
header = address;
+ entryContextMenuInfo = new EntryContextMenuInfo(header,
+ getResources().getString(R.string.phoneLabelsGroup));
if (sip.hasKindTypeColumn(kind)) {
text = SipAddress.getTypeLabel(getResources(), sip.getKindTypeColumn(kind),
sip.getLabel()).toString();
@@ -1217,6 +1272,7 @@
}
break;
default:
+ entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype);
icon = ResolveCache.getInstance(this).getIcon(
dataItem.getMimeType(), intent);
// Call mutate to create a new Drawable.ConstantState for color filtering
@@ -1258,7 +1314,7 @@
return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, intent,
alternateIcon, alternateIntent, alternateContentDescription, shouldApplyColor,
- isEditable);
+ isEditable, entryContextMenuInfo);
}
private List<Entry> dataItemsToEntries(List<DataItem> dataItems) {
@@ -1424,7 +1480,8 @@
/* alternateIntent = */ null,
/* alternateContentDescription = */ null,
/* shouldApplyColor = */ true,
- /* isEditable = */ false));
+ /* isEditable = */ false,
+ /* EntryContextMenuInfo = */ null));
}
return entries;
}
diff --git a/src/com/android/contacts/widget/MultiShrinkScroller.java b/src/com/android/contacts/widget/MultiShrinkScroller.java
index 632bb28..5f8bc14 100644
--- a/src/com/android/contacts/widget/MultiShrinkScroller.java
+++ b/src/com/android/contacts/widget/MultiShrinkScroller.java
@@ -885,13 +885,18 @@
return;
}
- float ratio = (toolbarHeight - mMinimumHeaderHeight)
+ final float ratio = (toolbarHeight - mMinimumHeaderHeight)
/ (float)(mMaximumHeaderHeight - mMinimumHeaderHeight);
final float minimumSize = mInvisiblePlaceholderTextView.getHeight();
- final float bezierOutput = mTextSizePathInterpolator.getInterpolation(ratio);
+ float bezierOutput = mTextSizePathInterpolator.getInterpolation(ratio);
float scale = (minimumSize + (mMaximumHeaderTextSize - minimumSize) * bezierOutput)
/ mMaximumHeaderTextSize;
+ // Clamp to reasonable/finite values before passing into framework. The values
+ // can be wacky before the first pre-render.
+ bezierOutput = (float) Math.min(bezierOutput, 1.0f);
+ scale = (float) Math.min(scale, 1.0f);
+
mLargeTextView.setScaleX(scale);
mLargeTextView.setScaleY(scale);
setInterpolatedTitleMargins(bezierOutput);