diff options
author | Chiao Cheng <chiaocheng@google.com> | 2013-09-24 15:40:43 -0700 |
---|---|---|
committer | Chiao Cheng <chiaocheng@google.com> | 2013-09-24 16:51:50 -0700 |
commit | c5b6a693d4773214ff8d3fcfa43d0a29581bb886 (patch) | |
tree | 3e9f4627fc2e8f725a1064cc5d7c56f004943c45 | |
parent | 8ea8569dbb1e4dba8e7dd558f82373cbb90e933c (diff) |
Adding missed call badge.
Bug: 10861718
Change-Id: I3a889a71cff7abac578da83d09dd7af23f3f88ca
-rw-r--r-- | res/drawable-hdpi/ic_call_log_blue.png | bin | 0 -> 1734 bytes | |||
-rw-r--r-- | res/drawable-mdpi/ic_call_log_blue.png | bin | 0 -> 1141 bytes | |||
-rw-r--r-- | res/drawable-xhdpi/ic_call_log_blue.png | bin | 0 -> 2386 bytes | |||
-rw-r--r-- | res/drawable-xxhdpi/ic_call_log_blue.png | bin | 0 -> 2967 bytes | |||
-rw-r--r-- | res/layout/call_log_list_item.xml | 6 | ||||
-rw-r--r-- | res/layout/call_log_list_item_extra.xml | 50 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogAdapter.java | 127 | ||||
-rw-r--r-- | src/com/android/dialer/list/PhoneFavoriteFragment.java | 24 | ||||
-rw-r--r-- | src/com/android/dialerbind/ObjectFactory.java | 3 | ||||
-rw-r--r-- | tests/src/com/android/dialer/calllog/CallLogAdapterTest.java | 2 |
10 files changed, 206 insertions, 6 deletions
diff --git a/res/drawable-hdpi/ic_call_log_blue.png b/res/drawable-hdpi/ic_call_log_blue.png Binary files differnew file mode 100644 index 000000000..92af15f7b --- /dev/null +++ b/res/drawable-hdpi/ic_call_log_blue.png diff --git a/res/drawable-mdpi/ic_call_log_blue.png b/res/drawable-mdpi/ic_call_log_blue.png Binary files differnew file mode 100644 index 000000000..b9209adca --- /dev/null +++ b/res/drawable-mdpi/ic_call_log_blue.png diff --git a/res/drawable-xhdpi/ic_call_log_blue.png b/res/drawable-xhdpi/ic_call_log_blue.png Binary files differnew file mode 100644 index 000000000..9d92573b0 --- /dev/null +++ b/res/drawable-xhdpi/ic_call_log_blue.png diff --git a/res/drawable-xxhdpi/ic_call_log_blue.png b/res/drawable-xxhdpi/ic_call_log_blue.png Binary files differnew file mode 100644 index 000000000..0a55a7572 --- /dev/null +++ b/res/drawable-xxhdpi/ic_call_log_blue.png diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml index c49b4b008..1bd448c5a 100644 --- a/res/layout/call_log_list_item.xml +++ b/res/layout/call_log_list_item.xml @@ -140,4 +140,10 @@ android:paddingTop="@dimen/call_log_inner_margin" android:paddingBottom="@dimen/call_log_inner_margin" /> + <!-- Displays the extra link section --> + <ViewStub android:id="@+id/link_stub" + android:layout="@layout/call_log_list_item_extra" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + </view> diff --git a/res/layout/call_log_list_item_extra.xml b/res/layout/call_log_list_item_extra.xml new file mode 100644 index 000000000..672abf12f --- /dev/null +++ b/res/layout/call_log_list_item_extra.xml @@ -0,0 +1,50 @@ +<?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 + --> + +<!-- Can't use merge here because this is referenced via a ViewStub --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/badge_container"> + + <View android:layout_width="match_parent" + android:layout_height="1px" + android:layout_marginStart="@dimen/call_log_outer_margin" + android:layout_marginEnd="@dimen/call_log_outer_margin" + android:background="@color/favorite_contacts_separator_color"/> + + <LinearLayout android:id="@+id/badge_link_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="@dimen/call_log_outer_margin" + android:paddingEnd="@dimen/call_log_outer_margin" + android:paddingTop="4dip" + android:paddingBottom="4dip" + android:background="?android:attr/selectableItemBackground" + android:clickable="true"> + <ImageView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/badge_image" + android:padding="@dimen/call_log_outer_margin"/> + <TextView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/badge_text" + android:textColor="@color/dialpad_primary_text_color" + android:layout_gravity="center_vertical"/> + </LinearLayout> +</FrameLayout>
\ No newline at end of file diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index 37dbdf3cf..b2493cf97 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -18,6 +18,7 @@ package com.android.dialer.calllog; import android.content.ContentValues; import android.content.Context; +import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; @@ -29,7 +30,10 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewStub; import android.view.ViewTreeObserver; +import android.widget.ImageView; +import android.widget.TextView; import com.android.common.widget.GroupingListAdapter; import com.android.contacts.common.ContactPhotoManager; @@ -48,6 +52,7 @@ import java.util.LinkedList; */ public class CallLogAdapter extends GroupingListAdapter implements ViewTreeObserver.OnPreDrawListener, CallLogGroupBuilder.GroupCreator { + /** Interface used to initiate a refresh of the content. */ public interface CallFetcher { public void fetchCalls(); @@ -182,6 +187,15 @@ public class CallLogAdapter extends GroupingListAdapter * action should be set to call a number instead of opening the detail page. */ private boolean mUseCallAsPrimaryAction = false; + private boolean mIsCallLog = true; + private int mNumMissedCalls = 0; + private int mNumMissedCallsShown = 0; + private Uri mCurrentPhotoUri; + + private View mBadgeContainer; + private ImageView mBadgeImageView; + private TextView mBadgeText; + /** Listener for the primary action in the list, opens the call details. */ private final View.OnClickListener mPrimaryActionListener = new View.OnClickListener() { @Override @@ -232,13 +246,15 @@ public class CallLogAdapter extends GroupingListAdapter }; public CallLogAdapter(Context context, CallFetcher callFetcher, - ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction) { + ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction, + boolean isCallLog) { super(context); mContext = context; mCallFetcher = callFetcher; mContactInfoHelper = contactInfoHelper; mUseCallAsPrimaryAction = useCallAsPrimaryAction; + mIsCallLog = isCallLog; mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE); mRequests = new LinkedList<ContactInfoRequest>(); @@ -614,12 +630,107 @@ public class CallLogAdapter extends GroupingListAdapter mViewTreeObserver.addOnPreDrawListener(this); } - postBindView(views, info, details); + bindBadge(view, info, details, callType); + } + + protected void bindBadge(View view, ContactInfo info, PhoneCallDetails details, int callType) { + + // Do not show badge in call log. + if (!mIsCallLog) { + final int numMissed = getNumMissedCalls(callType); + final ViewStub stub = (ViewStub) view.findViewById(R.id.link_stub); + if (shouldShowBadge(numMissed, info, details)) { + + // stub will be null if it was already inflated. + if (stub != null) { + final View inflated = stub.inflate(); + inflated.setVisibility(View.VISIBLE); + mBadgeContainer = inflated.findViewById(R.id.badge_link_container); + mBadgeImageView = (ImageView) inflated.findViewById(R.id.badge_image); + mBadgeText = (TextView) inflated.findViewById(R.id.badge_text); + } + + mBadgeContainer.setOnClickListener(getBadgeClickListener()); + mBadgeImageView.setImageResource(getBadgeImageResId()); + mBadgeText.setText(getBadgeText(numMissed)); + + mNumMissedCallsShown = numMissed; + } else { + // Hide badge if it was previously shown. + if (stub == null) { + final View container = view.findViewById(R.id.badge_container); + if (container != null) { + container.setVisibility(View.GONE); + } + } + } + } + } + + public void setMissedCalls(Cursor data) { + final int missed; + if (data == null) { + missed = 0; + } else { + missed = data.getCount(); + } + // Only need to update if the number of calls changed. + if (missed != mNumMissedCalls) { + mNumMissedCalls = missed; + notifyDataSetChanged(); + } + } + + protected View.OnClickListener getBadgeClickListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + final Intent intent = new Intent(mContext, CallLogActivity.class); + mContext.startActivity(intent); + } + }; + } + + /** + * Get the resource id for the image to be shown for the badge. + */ + protected int getBadgeImageResId() { + return R.drawable.ic_call_log_blue; + } + + /** + * Get the text to be shown for the badge. + * + * @param numMissed The number of missed calls. + */ + protected String getBadgeText(int numMissed) { + return mContext.getResources().getString(R.string.num_missed_calls, numMissed); } - protected void postBindView(CallLogListItemViews views, ContactInfo info, + /** + * Whether to show the badge. + * + * @param numMissedCalls The number of missed calls. + * @param info The contact info. + * @param details The call detail. + * @return {@literal true} if badge should be shown. {@literal false} otherwise. + */ + protected boolean shouldShowBadge(int numMissedCalls, ContactInfo info, PhoneCallDetails details) { - // no-op + // Do not process if the data has not changed (optimization since bind view is called + // multiple times due to contact lookup). + if (numMissedCalls == mNumMissedCallsShown) { + return false; + } + return numMissedCalls > 0; + } + + private int getNumMissedCalls(int callType) { + if (callType == Calls.MISSED_TYPE) { + // Exclude the current missed call shown in the shortcut. + return mNumMissedCalls - 1; + } + return mNumMissedCalls; } /** Checks whether the contact info from the call log matches the one from the contacts db. */ @@ -733,11 +844,19 @@ public class CallLogAdapter extends GroupingListAdapter } private void setPhoto(CallLogListItemViews views, long photoId, Uri contactUri) { + mCurrentPhotoUri = null; views.quickContactView.assignContactUri(contactUri); mContactPhotoManager.loadThumbnail(views.quickContactView, photoId, false /* darkTheme */); } private void setPhoto(CallLogListItemViews views, Uri photoUri, Uri contactUri) { + if (photoUri.equals(mCurrentPhotoUri)) { + // photo manager will perform a fade in transition. To avoid flicker, do not set the + // same photo multiple times. + return; + } + + mCurrentPhotoUri = photoUri; views.quickContactView.assignContactUri(contactUri); mContactPhotoManager.loadDirectoryPhoto(views.quickContactView, photoUri, false /* darkTheme */); diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java index d731786a5..32ec71c26 100644 --- a/src/com/android/dialer/list/PhoneFavoriteFragment.java +++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java @@ -30,6 +30,7 @@ import android.database.MatrixCursor; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; +import android.provider.CallLog; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -81,6 +82,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen * Used with LoaderManager. */ private static int LOADER_ID_CONTACT_TILE = 1; + private static int MISSED_CALL_LOADER = 2; private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE = "key_last_dismissed_call_shortcut_date"; @@ -94,6 +96,27 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen public void onCallNumberDirectly(String phoneNumber); } + private class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { + + @Override + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + final Uri uri = CallLog.Calls.CONTENT_URI; + final String[] projection = new String[] {CallLog.Calls.TYPE}; + final String selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE + + " AND " + CallLog.Calls.IS_READ + " = 0"; + return new CursorLoader(getActivity(), uri, projection, selection, null, null); + } + + @Override + public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) { + mCallLogAdapter.setMissedCalls(data); + } + + @Override + public void onLoaderReset(Loader<Cursor> cursorLoader) { + } + } + private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> { @Override public CursorLoader onCreateLoader(int id, Bundle args) { @@ -299,6 +322,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will // be called, on which we'll check if "all" contacts should be reloaded again or not. getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); + getLoaderManager().initLoader(MISSED_CALL_LOADER, null, new MissedCallLogLoaderListener()); } /** diff --git a/src/com/android/dialerbind/ObjectFactory.java b/src/com/android/dialerbind/ObjectFactory.java index 6286c05ba..c43dffcea 100644 --- a/src/com/android/dialerbind/ObjectFactory.java +++ b/src/com/android/dialerbind/ObjectFactory.java @@ -37,6 +37,7 @@ public class ObjectFactory { public static CallLogAdapter newCallLogAdapter(Context context, CallFetcher callFetcher, ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction, boolean isCallLog) { - return new CallLogAdapter(context, callFetcher, contactInfoHelper, useCallAsPrimaryAction); + return new CallLogAdapter(context, callFetcher, contactInfoHelper, useCallAsPrimaryAction, + isCallLog); } } diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java index 55e422498..12cdb2b99 100644 --- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java +++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java @@ -212,7 +212,7 @@ public class CallLogAdapterTest extends AndroidTestCase { public TestCallLogAdapter(Context context, CallFetcher callFetcher, ContactInfoHelper contactInfoHelper) { - super(context, callFetcher, contactInfoHelper, false); + super(context, callFetcher, contactInfoHelper, false, false); } @Override |