Replace text with icon for call type.
The design is to have an icon to indicate the call type instead of a
piece of text. Since we plan to have multiple icons for groups, use a
LinearLayout to store the actual icons.
Change-Id: I0055eca8eff8a9bc038aa6f152f486c18a6592c5
diff --git a/res/layout/call_log_phone_call_details.xml b/res/layout/call_log_phone_call_details.xml
index 71fd63e..e58de21 100644
--- a/res/layout/call_log_phone_call_details.xml
+++ b/res/layout/call_log_phone_call_details.xml
@@ -24,8 +24,8 @@
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
/>
- <TextView
- android:id="@+id/call_type"
+ <LinearLayout
+ android:id="@+id/call_types"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
@@ -34,13 +34,23 @@
android:layout_above="@id/number"
/>
<TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?attr/call_detail_primary_text_color"
+ android:layout_toRightOf="@id/call_types"
+ android:layout_above="@id/number"
+ android:layout_marginLeft="?attr/call_detail_date_margin"
+ />
+ <TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?attr/call_detail_primary_text_color"
android:layout_alignParentLeft="true"
- android:layout_above="@id/call_type"
+ android:layout_above="@id/call_types"
android:paddingBottom="2dp"
/>
</merge>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 801cc51..bb73840 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -57,6 +57,7 @@
<item name="call_detail_primary_text_color">#FFFFFF</item>
<item name="call_detail_action_icon_size">50dip</item>
<item name="call_detail_secondary_background_color">#FFFFFF</item>
+ <item name="call_detail_date_margin">5dip</item>
</style>
<style name="ContactDetailActivityTheme" parent="android:Theme.Holo.Light">
@@ -141,6 +142,7 @@
<attr name="call_detail_primary_text_color" format="color" />
<attr name="call_detail_primary_background_color" format="color" />
<attr name="call_detail_secondary_background_color" format="color" />
+ <attr name="call_detail_date_margin" format="dimension" />
</declare-styleable>
<declare-styleable name="CallLogActivity">
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 43376ca..f87f8a4 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -115,7 +115,12 @@
mResources = getResources();
mPhoneCallDetailsViews = PhoneCallDetailsViews.fromView(getWindow().getDecorView());
- mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(getResources(), getVoicemailNumber());
+ mPhoneCallDetailsHelper = new PhoneCallDetailsHelper(this, getResources(),
+ getVoicemailNumber(),
+ getResources().getDrawable(R.drawable.ic_call_log_list_incoming_call),
+ getResources().getDrawable(R.drawable.ic_call_log_list_outgoing_call),
+ getResources().getDrawable(R.drawable.ic_call_log_list_missed_call),
+ getResources().getDrawable(R.drawable.ic_call_log_list_voicemail));
mCallActionView = findViewById(R.id.call);
mContactPhotoView = (ImageView) findViewById(R.id.contact_photo);
mContactBackgroundView = (ImageView) findViewById(R.id.contact_background);
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index fc96a89..78ca252 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -19,8 +19,10 @@
import com.android.contacts.format.FormatUtils;
import com.android.internal.telephony.CallerInfo;
+import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.PhoneNumberUtils;
@@ -28,16 +30,25 @@
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.View;
+import android.widget.ImageView;
/**
* Helper class to fill in the views in {@link PhoneCallDetailsViews}.
*/
public class PhoneCallDetailsHelper {
+ private final Context mContext;
private final Resources mResources;
private final String mVoicemailNumber;
- private final String mTypeIncomingText;
- private final String mTypeOutgoingText;
- private final String mTypeMissedText;
+ /** Icon for incoming calls. */
+ private final Drawable mIncomingDrawable;
+ /** Icon for outgoing calls. */
+ private final Drawable mOutgoingDrawable;
+ /** Icon for missed calls. */
+ private final Drawable mMissedDrawable;
+ /** Icon for voicemails. */
+ private final Drawable mVoicemailDrawable;
+ /** The injected current time in milliseconds since the epoch. Used only by tests. */
+ private Long mCurrentTimeMillisForTest;
/**
* Creates a new instance of the helper.
@@ -46,12 +57,16 @@
*
* @param resources used to look up strings
*/
- public PhoneCallDetailsHelper(Resources resources, String voicemailNumber) {
+ public PhoneCallDetailsHelper(Context context, Resources resources, String voicemailNumber,
+ Drawable incomingDrawable, Drawable outgoingDrawable, Drawable missedDrawable,
+ Drawable voicemailDrawable) {
+ mContext = context;
mResources = resources;
mVoicemailNumber = voicemailNumber;
- mTypeIncomingText = mResources.getString(R.string.type_incoming);
- mTypeOutgoingText = mResources.getString(R.string.type_outgoing);
- mTypeMissedText = mResources.getString(R.string.type_missed);
+ mIncomingDrawable = incomingDrawable;
+ mOutgoingDrawable = outgoingDrawable;
+ mMissedDrawable = missedDrawable;
+ mVoicemailDrawable = voicemailDrawable;
}
/**
@@ -67,31 +82,30 @@
public void setPhoneCallDetails(PhoneCallDetailsViews views, long date,
int callType, CharSequence name, CharSequence number, int numberType,
CharSequence numberLabel) {
- CharSequence callTypeText = "";
+ Drawable callTypeDrawable = null;
switch (callType) {
case Calls.INCOMING_TYPE:
- callTypeText = mTypeIncomingText;
+ callTypeDrawable = mIncomingDrawable;
break;
case Calls.OUTGOING_TYPE:
- callTypeText = mTypeOutgoingText;
+ callTypeDrawable = mOutgoingDrawable;
break;
case Calls.MISSED_TYPE:
- callTypeText = mTypeMissedText;
+ callTypeDrawable = mMissedDrawable;
+ break;
+
+ case Calls.VOICEMAIL_TYPE:
+ callTypeDrawable = mVoicemailDrawable;
break;
}
-
CharSequence shortDateText =
DateUtils.getRelativeTimeSpanString(date,
- System.currentTimeMillis(),
+ getCurrentTimeMillis(),
DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_ABBREV_RELATIVE);
- CharSequence callTypeAndDateText = FormatUtils.applyStyleToSpan(Typeface.BOLD,
- callTypeText + " " + shortDateText, 0, callTypeText.length(),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-
CharSequence numberFormattedLabel = null;
// Only show a label if the number is shown and it is not a SIP address.
if (!TextUtils.isEmpty(number) && !PhoneNumberUtils.isUriNumber(number.toString())) {
@@ -114,17 +128,22 @@
}
}
- views.mCallTypeAndDateView.setText(callTypeAndDateText);
- views.mCallTypeAndDateView.setVisibility(View.VISIBLE);
- views.mNameView.setText(nameText);
- views.mNameView.setVisibility(View.VISIBLE);
+ ImageView callTypeImage = new ImageView(mContext);
+ callTypeImage.setImageDrawable(callTypeDrawable);
+ views.callTypesLayout.removeAllViews();
+ views.callTypesLayout.addView(callTypeImage);
+
+ views.dateView.setText(shortDateText);
+ views.dateView.setVisibility(View.VISIBLE);
+ views.nameView.setText(nameText);
+ views.nameView.setVisibility(View.VISIBLE);
// Do not show the number if it is not available. This happens if we have only the number,
// in which case the number is shown in the name field instead.
if (!TextUtils.isEmpty(numberText)) {
- views.mNumberView.setText(numberText);
- views.mNumberView.setVisibility(View.VISIBLE);
+ views.numberView.setText(numberText);
+ views.numberView.setVisibility(View.VISIBLE);
} else {
- views.mNumberView.setVisibility(View.GONE);
+ views.numberView.setVisibility(View.GONE);
}
}
@@ -146,4 +165,21 @@
}
return number;
}
+
+ public void setCurrentTimeForTest(long currentTimeMillis) {
+ mCurrentTimeMillisForTest = currentTimeMillis;
+ }
+
+ /**
+ * Returns the current time in milliseconds since the epoch.
+ * <p>
+ * It can be injected in tests using {@link #setCurrentTimeForTest(long)}.
+ */
+ private long getCurrentTimeMillis() {
+ if (mCurrentTimeMillisForTest == null) {
+ return System.currentTimeMillis();
+ } else {
+ return mCurrentTimeMillisForTest;
+ }
+ }
}
diff --git a/src/com/android/contacts/PhoneCallDetailsViews.java b/src/com/android/contacts/PhoneCallDetailsViews.java
index c2819c3..483ec65 100644
--- a/src/com/android/contacts/PhoneCallDetailsViews.java
+++ b/src/com/android/contacts/PhoneCallDetailsViews.java
@@ -17,37 +17,42 @@
package com.android.contacts;
import android.view.View;
+import android.widget.LinearLayout;
import android.widget.TextView;
/**
* Encapsulates the views that are used to display the details of a phone call in the call log.
*/
public final class PhoneCallDetailsViews {
- public final TextView mNameView;
- public final TextView mCallTypeAndDateView;
- public final TextView mNumberView;
+ public final TextView nameView;
+ public final LinearLayout callTypesLayout;
+ public final TextView dateView;
+ public final TextView numberView;
- private PhoneCallDetailsViews(TextView nameView, TextView callTypeAndDateView,
- TextView numberView) {
- mNameView = nameView;
- mCallTypeAndDateView = callTypeAndDateView;
- mNumberView = numberView;
+ private PhoneCallDetailsViews(TextView nameView, LinearLayout callTypesLayout,
+ TextView dateView, TextView numberView) {
+ this.nameView = nameView;
+ this.callTypesLayout = callTypesLayout;
+ this.dateView = dateView;
+ this.numberView = numberView;
}
/**
* Create a new instance by extracting the elements from the given view.
* <p>
* The view should contain three text views with identifiers {@code R.id.name},
- * {@code R.id.call_type}, and {@code R.id.number}.
+ * {@code R.id.date}, and {@code R.id.number}, and a linear layout with identifier
+ * {@code R.id.call_types}.
*/
public static PhoneCallDetailsViews fromView(View view) {
return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name),
- (TextView) view.findViewById(R.id.call_type),
+ (LinearLayout) view.findViewById(R.id.call_types),
+ (TextView) view.findViewById(R.id.date),
(TextView) view.findViewById(R.id.number));
}
public static PhoneCallDetailsViews createForTest(TextView nameView,
- TextView callTypeAndDateView, TextView numberView) {
- return new PhoneCallDetailsViews(nameView, callTypeAndDateView, numberView);
+ LinearLayout callTypesLayout, TextView dateView, TextView numberView) {
+ return new PhoneCallDetailsViews(nameView, callTypesLayout, dateView, numberView);
}
}
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index ab00382..5c02959 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -16,13 +16,22 @@
package com.android.contacts;
+import com.android.contacts.util.LocaleTestUtils;
import com.android.internal.telephony.CallerInfo;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.provider.CallLog.Calls;
import android.test.AndroidTestCase;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
/**
* Unit tests for {@link PhoneCallDetailsHelper}.
*/
@@ -31,6 +40,16 @@
private static final String TEST_VOICEMAIL_NUMBER = "125";
/** The date of the call log entry. */
private static final long TEST_DATE = 1300000000;
+ /** The number of the caller/callee in the log entry. */
+ private static final String TEST_NUMBER = "1-412-555-5555";
+ /** A drawable to be used for incoming calls. */
+ private static final Drawable TEST_INCOMING_DRAWABLE = new ColorDrawable(Color.BLACK);
+ /** A drawable to be used for outgoing calls. */
+ private static final Drawable TEST_OUTGOING_DRAWABLE = new ColorDrawable(Color.BLUE);
+ /** A drawable to be used for missed calls. */
+ private static final Drawable TEST_MISSED_DRAWABLE = new ColorDrawable(Color.RED);
+ /** A drawable to be used for voicemails. */
+ private static final Drawable TEST_VOICEMAIL_DRAWABLE = new ColorDrawable(Color.CYAN);
/** The object under test. */
private PhoneCallDetailsHelper mHelper;
@@ -41,9 +60,11 @@
protected void setUp() throws Exception {
super.setUp();
Context context = getContext();
- mHelper = new PhoneCallDetailsHelper(context.getResources(), TEST_VOICEMAIL_NUMBER);
- mViews = PhoneCallDetailsViews.createForTest(new TextView(context), new TextView(context),
- new TextView(context));
+ mHelper = new PhoneCallDetailsHelper(context, context.getResources(),
+ TEST_VOICEMAIL_NUMBER, TEST_INCOMING_DRAWABLE, TEST_OUTGOING_DRAWABLE,
+ TEST_MISSED_DRAWABLE, TEST_VOICEMAIL_DRAWABLE);
+ mViews = PhoneCallDetailsViews.createForTest(new TextView(context),
+ new LinearLayout(context), new TextView(context), new TextView(context));
}
@Override
@@ -78,6 +99,47 @@
assertNameEquals("1-412-555-1212");
}
+ public void testSetPhoneCallDetails_Date() {
+ LocaleTestUtils localeTestUtils = new LocaleTestUtils(getContext());
+ localeTestUtils.setLocale(Locale.US);
+ try {
+ mHelper.setCurrentTimeForTest(
+ new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis());
+
+ setPhoneCallDetailsWithDate(
+ new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis());
+ assertDateEquals("0 mins ago");
+
+ setPhoneCallDetailsWithDate(
+ new GregorianCalendar(2011, 5, 3, 12, 0, 0).getTimeInMillis());
+ assertDateEquals("1 hour ago");
+
+ setPhoneCallDetailsWithDate(
+ new GregorianCalendar(2011, 5, 2, 13, 0, 0).getTimeInMillis());
+ assertDateEquals("yesterday");
+
+ setPhoneCallDetailsWithDate(
+ new GregorianCalendar(2011, 5, 1, 13, 0, 0).getTimeInMillis());
+ assertDateEquals("2 days ago");
+ } finally {
+ localeTestUtils.restoreLocale();
+ }
+ }
+
+ public void testSetPhoneCallDetails_CallType() {
+ setPhoneCallDetailsWithCallType(Calls.INCOMING_TYPE);
+ assertCallTypeIconsEquals(TEST_INCOMING_DRAWABLE);
+
+ setPhoneCallDetailsWithCallType(Calls.OUTGOING_TYPE);
+ assertCallTypeIconsEquals(TEST_OUTGOING_DRAWABLE);
+
+ setPhoneCallDetailsWithCallType(Calls.MISSED_TYPE);
+ assertCallTypeIconsEquals(TEST_MISSED_DRAWABLE);
+
+ setPhoneCallDetailsWithCallType(Calls.VOICEMAIL_TYPE);
+ assertCallTypeIconsEquals(TEST_VOICEMAIL_DRAWABLE);
+ }
+
/** Asserts that the name text field contains the value of the given string resource. */
private void assertNameEqualsResource(int resId) {
assertNameEquals(getContext().getString(resId));
@@ -85,11 +147,36 @@
/** Asserts that the name text field contains the given string value. */
private void assertNameEquals(String text) {
- assertEquals(text, mViews.mNameView.getText().toString());
+ assertEquals(text, mViews.nameView.getText().toString());
+ }
+
+ /** Asserts that the date text field contains the given string value. */
+ private void assertDateEquals(String text) {
+ assertEquals(text, mViews.dateView.getText().toString());
+ }
+
+ /** Asserts that the call type linear layout contains the images with the given drawables. */
+ private void assertCallTypeIconsEquals(Drawable... drawables) {
+ assertEquals(drawables.length, mViews.callTypesLayout.getChildCount());
+ for (int index = 0; index < drawables.length; ++index) {
+ Drawable drawable = drawables[index];
+ ImageView imageView = (ImageView) mViews.callTypesLayout.getChildAt(index);
+ assertEquals(drawable, imageView.getDrawable());
+ }
}
/** Sets the phone call details with default values and the given number. */
private void setPhoneCallDetailsWithNumber(String number) {
mHelper.setPhoneCallDetails(mViews, TEST_DATE, Calls.INCOMING_TYPE, "", number, 0, "");
}
+
+ /** Sets the phone call details with default values and the given date. */
+ private void setPhoneCallDetailsWithDate(long date) {
+ mHelper.setPhoneCallDetails(mViews, date, Calls.INCOMING_TYPE, "", TEST_NUMBER, 0, "");
+ }
+
+ /** Sets the phone call details with default values and the given call type. */
+ private void setPhoneCallDetailsWithCallType(int callType) {
+ mHelper.setPhoneCallDetails(mViews, TEST_DATE, callType, "", TEST_NUMBER, 0, "");
+ }
}