Update the call details UI.
New call details UI:
- Big picture at the top with a black overlay
- Small contact picture on the side
- Details of the call next to the picture
- Action button for calling back
- Action button (disabled) for deleting: waiting for asset
- Details at the bottom
This commit still preserves the list view with action to keep the app
fully usable. These will be replaced once we use a quick contact badge
instead of a plain contact picture.
Change-Id: I8e8218c3ef863abe9b33d4b677afa3c6650b9f77
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index b3c68ef..0931e3d 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -16,6 +16,7 @@
package com.android.contacts;
+import com.android.contacts.format.FormatUtils;
import com.android.internal.telephony.CallerInfo;
import android.app.ListActivity;
@@ -25,16 +26,18 @@
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
+import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
+import android.provider.Contacts.Intents.Insert;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.Contacts.Intents.Insert;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
+import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.KeyEvent;
@@ -57,16 +60,23 @@
AdapterView.OnItemClickListener {
private static final String TAG = "CallDetail";
- private TextView mCallType;
- private ImageView mCallTypeIcon;
- private TextView mCallTime;
- private TextView mCallDuration;
+ private TextView mNameView;
+ private TextView mCallTypeView;
+ private TextView mNumberView;
+ private TextView mCallTimeView;
+ private TextView mCallDurationView;
+ private View mCallActionView;
+ private ImageView mContactPhotoView;
+ private ImageView mContactBackgroundView;
private String mNumber = null;
private String mDefaultCountryIso;
/* package */ LayoutInflater mInflater;
/* package */ Resources mResources;
+ /** Helper to load contact photos. */
+ private ContactPhotoManager mContactPhotoManager;
+ /** Attached to the call action button in the UI. */
static final String[] CALL_LOG_PROJECTION = new String[] {
CallLog.Calls.DATE,
@@ -89,6 +99,7 @@
PhoneLookup.LABEL,
PhoneLookup.NUMBER,
PhoneLookup.NORMALIZED_NUMBER,
+ PhoneLookup.PHOTO_ID,
};
static final int COLUMN_INDEX_ID = 0;
static final int COLUMN_INDEX_NAME = 1;
@@ -96,6 +107,7 @@
static final int COLUMN_INDEX_LABEL = 3;
static final int COLUMN_INDEX_NUMBER = 4;
static final int COLUMN_INDEX_NORMALIZED_NUMBER = 5;
+ static final int COLUMN_INDEX_PHOTO_ID = 6;
@Override
protected void onCreate(Bundle icicle) {
@@ -106,12 +118,16 @@
mInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
mResources = getResources();
- mCallType = (TextView) findViewById(R.id.type);
- mCallTypeIcon = (ImageView) findViewById(R.id.icon);
- mCallTime = (TextView) findViewById(R.id.time);
- mCallDuration = (TextView) findViewById(R.id.duration);
+ mNameView = (TextView) findViewById(R.id.name);
+ mCallTypeView = (TextView) findViewById(R.id.call_type);
+ mNumberView = (TextView) findViewById(R.id.number);
+ mCallActionView = findViewById(R.id.call);
+ mContactPhotoView = (ImageView) findViewById(R.id.contact_photo);
+ mContactBackgroundView = (ImageView) findViewById(R.id.contact_background);
+ mCallTimeView = (TextView) findViewById(R.id.time);
+ mCallDurationView = (TextView) findViewById(R.id.duration);
mDefaultCountryIso = ContactsUtils.getCurrentCountryIso(this);
-
+ mContactPhotoManager = ContactPhotoManager.getInstance(this);
getListView().setOnItemClickListener(this);
}
@@ -163,85 +179,104 @@
CharSequence dateClause = DateUtils.formatDateRange(this, date, date,
DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_YEAR);
- mCallTime.setText(dateClause);
+ mCallTimeView.setText(dateClause);
// Set the duration
if (callType == Calls.MISSED_TYPE) {
- mCallDuration.setVisibility(View.GONE);
+ mCallDurationView.setVisibility(View.GONE);
} else {
- mCallDuration.setVisibility(View.VISIBLE);
- mCallDuration.setText(formatDuration(duration));
+ mCallDurationView.setVisibility(View.VISIBLE);
+ mCallDurationView.setText(formatDuration(duration));
}
- // Set the call type icon and caption
- String callText = null;
+ CharSequence shortDateText =
+ DateUtils.getRelativeTimeSpanString(date,
+ System.currentTimeMillis(),
+ DateUtils.MINUTE_IN_MILLIS,
+ DateUtils.FORMAT_ABBREV_RELATIVE);
+
+ CharSequence callTypeText = "";
switch (callType) {
case Calls.INCOMING_TYPE:
- mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_incoming_call);
- mCallType.setText(R.string.type_incoming);
- callText = getString(R.string.callBack);
+ callTypeText = getString(R.string.type_incoming);
break;
case Calls.OUTGOING_TYPE:
- mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_outgoing_call);
- mCallType.setText(R.string.type_outgoing);
- callText = getString(R.string.callAgain);
+ callTypeText = getString(R.string.type_outgoing);
break;
case Calls.MISSED_TYPE:
- mCallTypeIcon.setImageResource(R.drawable.ic_call_log_header_missed_call);
- mCallType.setText(R.string.type_missed);
- callText = getString(R.string.returnCall);
+ callTypeText = getString(R.string.type_missed);
break;
}
+ mCallTypeView.setText(
+ getString(R.string.call_type_and_date,
+ FormatUtils.applyStyleToSpan(Typeface.BOLD,
+ callTypeText, 0, callTypeText.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE),
+ shortDateText));
+
+ long photoId = 0L;
+ CharSequence nameText = "";
+ CharSequence numberText = "";
if (mNumber.equals(CallerInfo.UNKNOWN_NUMBER) ||
mNumber.equals(CallerInfo.PRIVATE_NUMBER)) {
- // List is empty, let the empty view show instead.
- TextView emptyText = (TextView) findViewById(R.id.emptyText);
- if (emptyText != null) {
- emptyText.setText(mNumber.equals(CallerInfo.PRIVATE_NUMBER)
- ? R.string.private_num : R.string.unknown);
- }
+ nameText = getString(mNumber.equals(CallerInfo.PRIVATE_NUMBER)
+ ? R.string.private_num : R.string.unknown);
+ numberText = "";
+ mCallActionView.setVisibility(View.GONE);
} else {
// Perform a reverse-phonebook lookup to find the PERSON_ID
- String callLabel = null;
+ CharSequence callLabel = null;
Uri personUri = null;
Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(mNumber));
- Cursor phonesCursor = resolver.query(phoneUri, PHONES_PROJECTION, null, null, null);
+ Cursor phonesCursor = resolver.query(
+ phoneUri, PHONES_PROJECTION, null, null, null);
try {
if (phonesCursor != null && phonesCursor.moveToFirst()) {
long personId = phonesCursor.getLong(COLUMN_INDEX_ID);
personUri = ContentUris.withAppendedId(
Contacts.CONTENT_URI, personId);
- callText = getString(R.string.recentCalls_callNumber,
- phonesCursor.getString(COLUMN_INDEX_NAME));
+ nameText = phonesCursor.getString(COLUMN_INDEX_NAME);
+ photoId = phonesCursor.getLong(COLUMN_INDEX_PHOTO_ID);
mNumber = PhoneNumberUtils.formatNumber(
phonesCursor.getString(COLUMN_INDEX_NUMBER),
phonesCursor.getString(COLUMN_INDEX_NORMALIZED_NUMBER),
countryIso);
- callLabel = Phone.getDisplayLabel(this,
+ callLabel = Phone.getTypeLabel(getResources(),
phonesCursor.getInt(COLUMN_INDEX_TYPE),
- phonesCursor.getString(COLUMN_INDEX_LABEL)).toString();
+ phonesCursor.getString(COLUMN_INDEX_LABEL));
} else {
mNumber = PhoneNumberUtils.formatNumber(mNumber, countryIso);
}
} finally {
- if (phonesCursor != null) phonesCursor.close();
+ if (phonesCursor != null) phonesCursor.close();
+ }
+
+ mCallActionView.setVisibility(View.VISIBLE);
+ mCallActionView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
+ Uri.fromParts("tel", mNumber, null));
+ startActivity(callIntent);
+ }
+ });
+
+ if (callLabel != null) {
+ numberText = FormatUtils.applyStyleToSpan(Typeface.BOLD,
+ callLabel + " " + mNumber, 0,
+ callLabel.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ } else {
+ numberText = mNumber;
}
// Build list of various available actions
List<ViewEntry> actions = new ArrayList<ViewEntry>();
- Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
- Uri.fromParts("tel", mNumber, null));
- ViewEntry entry = new ViewEntry(android.R.drawable.sym_action_call, callText,
- callIntent);
- entry.number = mNumber;
- entry.label = callLabel;
- actions.add(entry);
-
Intent smsIntent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("sms", mNumber, null));
actions.add(new ViewEntry(R.drawable.sym_action_sms,
@@ -264,6 +299,10 @@
ViewAdapter adapter = new ViewAdapter(this, actions);
setListAdapter(adapter);
}
+ mNameView.setText(nameText);
+ mNumberView.setText(numberText);
+
+ loadContactPhotos(photoId);
} else {
// Something went wrong reading in our primary data, so we're going to
// bail out and show error to users.
@@ -278,6 +317,25 @@
}
}
+ /** Load the contact photos and places them in the corresponding views. */
+ private void loadContactPhotos(final long photoId) {
+ // There seem to be a limitation in the ContactPhotoManager that does not allow requesting
+ // two photos at once.
+ // TODO: Figure out the problem with ContactPhotoManager and remove this nonsense.
+ mContactPhotoView.post(new Runnable() {
+ @Override
+ public void run() {
+ mContactPhotoManager.loadPhoto(mContactPhotoView, photoId);
+ mContactPhotoView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mContactPhotoManager.loadPhoto(mContactBackgroundView, photoId);
+ }
+ }, 100);
+ }
+ });
+ }
+
private String formatDuration(long elapsedSeconds) {
long minutes = 0;
long seconds = 0;
@@ -316,18 +374,22 @@
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
+ @Override
public int getCount() {
return mActions.size();
}
+ @Override
public Object getItem(int position) {
return mActions.get(position);
}
+ @Override
public long getItemId(int position) {
return position;
}
+ @Override
public View getView(int position, View convertView, ViewGroup parent) {
// Make sure we have a valid convertView to start with
if (convertView == null) {
@@ -368,7 +430,8 @@
}
}
- public void onItemClick(AdapterView parent, View view, int position, long id) {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Handle passing action off to correct handler.
if (view.getTag() instanceof ViewEntry) {
ViewEntry entry = (ViewEntry) view.getTag();