summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuzhou <jiayuzhou@google.com>2018-04-21 17:20:47 -0700
committerYuzhou <jiayuzhou@google.com>2018-04-30 14:19:51 -0700
commit3fe91522bb3db3b2f8d74a3fed935e35a9bcbb2d (patch)
tree31739ece130d41a0a7c68d26cbe2da3a3a19615f
parent8ea3d43c77dcec55650f7e865987097f56b0e002 (diff)
downloadplatform_packages_apps_Car_Dialer-3fe91522bb3db3b2f8d74a3fed935e35a9bcbb2d.tar.gz
platform_packages_apps_Car_Dialer-3fe91522bb3db3b2f8d74a3fed935e35a9bcbb2d.tar.bz2
platform_packages_apps_Car_Dialer-3fe91522bb3db3b2f8d74a3fed935e35a9bcbb2d.zip
DO NOT MERGE Implement Contact fragment.
Test: build and load the app. Bug: 77980012. Change-Id: I1b811172f420e58f0f093b5654fa9dc6e03629fb
-rw-r--r--res/drawable/ic_call_end.xml2
-rw-r--r--res/drawable/ic_contact.xml24
-rw-r--r--res/drawable/ic_dialpad_activated.xml2
-rw-r--r--res/drawable/ic_mute_call_activated.xml2
-rw-r--r--res/layout/contact_list_fragment.xml69
-rw-r--r--res/layout/ic_arrow_back.xml24
-rw-r--r--res/layout/on_going_call_controller_bar_fragment.xml2
-rw-r--r--res/values-w748dp/dimens.xml2
-rw-r--r--res/values/strings.xml3
-rw-r--r--src/com/android/car/dialer/ContactDetailsFragment.java15
-rw-r--r--src/com/android/car/dialer/ContactResultsFragment.java18
-rw-r--r--src/com/android/car/dialer/ContactSearchActivity.java15
-rw-r--r--src/com/android/car/dialer/TelecomActivity.java27
-rw-r--r--src/com/android/car/dialer/ui/CallHistoryListItemProvider.java13
-rw-r--r--src/com/android/car/dialer/ui/ContactListFragment.java205
-rw-r--r--src/com/android/car/dialer/ui/ContactListItemProvider.java71
-rw-r--r--src/com/android/car/dialer/ui/listitem/CallLogListItem.java53
-rw-r--r--src/com/android/car/dialer/ui/listitem/ContactListItem.java44
18 files changed, 502 insertions, 89 deletions
diff --git a/res/drawable/ic_call_end.xml b/res/drawable/ic_call_end.xml
index 7c7e73ff..2b008b93 100644
--- a/res/drawable/ic_call_end.xml
+++ b/res/drawable/ic_call_end.xml
@@ -16,4 +16,4 @@
.18 -.43 .29 -.71 .29 -.27
0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15
9.25 13.6 9 12 9z" />
-</vector> \ No newline at end of file
+</vector>
diff --git a/res/drawable/ic_contact.xml b/res/drawable/ic_contact.xml
new file mode 100644
index 00000000..7b547753
--- /dev/null
+++ b/res/drawable/ic_contact.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:width="48dp"
+ android:height="48dp">
+ <path
+ android:pathData="M6 10l0 28c0 2.21 1.79 4 4 4l28 0c2.21 0 4 -1.79 4 -4L42 10C42 7.79 40.21 6 38 6L10 6C7.79 6 6 7.79 6 10Zm24 8c0 3.32 -2.69 6 -6 6 -3.31 0 -6 -2.68 -6 -6 0 -3.31 2.69 -6 6 -6 3.31 0 6 2.69 6 6zM12 34c0 -4 8 -6.2 12 -6.2 4 0 12 2.2 12 6.2l0 2 -24 0 0 -2z"
+ android:fillColor="#000000" />
+</vector> \ No newline at end of file
diff --git a/res/drawable/ic_dialpad_activated.xml b/res/drawable/ic_dialpad_activated.xml
index 0d2a5221..42f5d8ce 100644
--- a/res/drawable/ic_dialpad_activated.xml
+++ b/res/drawable/ic_dialpad_activated.xml
@@ -19,4 +19,4 @@
android:drawable="@drawable/button_active_state_ring"/>
<item
android:drawable="@drawable/ic_dialpad_normal"/>
-</layer-list> \ No newline at end of file
+</layer-list>
diff --git a/res/drawable/ic_mute_call_activated.xml b/res/drawable/ic_mute_call_activated.xml
index 5d0a6b8e..822c7363 100644
--- a/res/drawable/ic_mute_call_activated.xml
+++ b/res/drawable/ic_mute_call_activated.xml
@@ -19,4 +19,4 @@
android:drawable="@drawable/button_active_state_ring"/>
<item
android:drawable="@drawable/ic_mute_call_normal"/>
-</layer-list> \ No newline at end of file
+</layer-list>
diff --git a/res/layout/contact_list_fragment.xml b/res/layout/contact_list_fragment.xml
new file mode 100644
index 00000000..ce87195d
--- /dev/null
+++ b/res/layout/contact_list_fragment.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false">
+
+ <androidx.car.widget.PagedListView
+ android:id="@+id/list_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/car_app_bar_height"
+ android:clipChildren="false"/>
+
+ <FrameLayout
+ android:id="@+id/contact_detail_container"
+ android:background="@color/car_grey_200"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone">
+ <android.support.constraint.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/car_app_bar_height">
+ <ImageView
+ android:id="@+id/back_button"
+ android:layout_width="@dimen/car_touch_target_size"
+ android:layout_height="@dimen/car_touch_target_size"
+ android:scaleType="center"
+ android:src="@drawable/ic_arrow_back"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="@+id/margin_guideline"
+ app:layout_constraintTop_toTopOf="parent"/>
+ <android.support.constraint.Guideline
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/margin_guideline"
+ app:layout_constraintGuide_begin="@dimen/car_margin"
+ android:orientation="vertical"/>
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/back_button"
+ app:layout_constraintTop_toTopOf="parent"/>
+ </android.support.constraint.ConstraintLayout>
+ <FrameLayout
+ android:id="@+id/contact_detail_fragment_container"
+ android:layout_marginTop="@dimen/car_app_bar_height"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </FrameLayout>
+</FrameLayout> \ No newline at end of file
diff --git a/res/layout/ic_arrow_back.xml b/res/layout/ic_arrow_back.xml
new file mode 100644
index 00000000..0283b490
--- /dev/null
+++ b/res/layout/ic_arrow_back.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:width="44dp"
+ android:height="44dp">
+ <path
+ android:pathData="M40 22L15.66 22 26.83 10.83 24 8 8 24 24 40 26.83 37.17 15.66 26 40 26 40 22Z"
+ android:fillColor="#000000" />
+</vector> \ No newline at end of file
diff --git a/res/layout/on_going_call_controller_bar_fragment.xml b/res/layout/on_going_call_controller_bar_fragment.xml
index 308c22c0..7e1c0864 100644
--- a/res/layout/on_going_call_controller_bar_fragment.xml
+++ b/res/layout/on_going_call_controller_bar_fragment.xml
@@ -85,4 +85,4 @@ limitations under the License.
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@color/contact_badge"/>
-</android.support.constraint.ConstraintLayout> \ No newline at end of file
+</android.support.constraint.ConstraintLayout>
diff --git a/res/values-w748dp/dimens.xml b/res/values-w748dp/dimens.xml
index 9c2c2a83..1a856737 100644
--- a/res/values-w748dp/dimens.xml
+++ b/res/values-w748dp/dimens.xml
@@ -16,4 +16,4 @@
<resources>
<!-- The max width of content in apps for adaptive responsive -->
<dimen name="apps_max_content_width">748dp</dimen>
-</resources> \ No newline at end of file
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 086752aa..98a2d345 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -77,6 +77,9 @@
<!-- Button label to dial a manually entered phone number -->
<string name="dial_a_number">Dial a number</string>
+ <!-- Menu label for the call history [CHAR LIMIT=30] -->
+ <string name="contact_menu_label">Contact</string>
+
<!-- TODO: we do not need to localize this, figure out how to build ignoring it -->
<string name="one">1</string>
<string name="two">2</string>
diff --git a/src/com/android/car/dialer/ContactDetailsFragment.java b/src/com/android/car/dialer/ContactDetailsFragment.java
index f2f378aa..3143dfd7 100644
--- a/src/com/android/car/dialer/ContactDetailsFragment.java
+++ b/src/com/android/car/dialer/ContactDetailsFragment.java
@@ -15,17 +15,17 @@
*/
package com.android.car.dialer;
-import android.app.Fragment;
-import android.app.LoaderManager;
-import android.content.CursorLoader;
import android.content.Intent;
-import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.Pair;
@@ -72,7 +72,9 @@ public class ContactDetailsFragment extends Fragment
public static ContactDetailsFragment newInstance(Uri uri,
@Nullable RecyclerView.OnScrollListener listener) {
ContactDetailsFragment fragment = new ContactDetailsFragment();
- fragment.addOnScrollListener(listener);
+ if (listener != null) {
+ fragment.addOnScrollListener(listener);
+ }
Bundle args = new Bundle();
args.putParcelable(KEY_URI, uri);
@@ -209,7 +211,8 @@ public class ContactDetailsFragment extends Fragment
}
// Fetch the phone number from the contacts db using another loader.
- getLoaderManager().initLoader(PHONE_LOADER_QUERY_ID, null,
+ LoaderManager.getInstance(ContactDetailsFragment.this).initLoader(PHONE_LOADER_QUERY_ID,
+ null,
new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
diff --git a/src/com/android/car/dialer/ContactResultsFragment.java b/src/com/android/car/dialer/ContactResultsFragment.java
index 5ecd3f7d..7fa4c893 100644
--- a/src/com/android/car/dialer/ContactResultsFragment.java
+++ b/src/com/android/car/dialer/ContactResultsFragment.java
@@ -16,14 +16,14 @@
package com.android.car.dialer;
-import android.app.Fragment;
-import android.app.LoaderManager;
-import android.content.CursorLoader;
-import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
@@ -124,7 +124,7 @@ public class ContactResultsFragment extends Fragment implements
if (!TextUtils.isEmpty(mSearchQuery)) {
// Calling restartLoader so that the loader is always re-created with the new
// search query.
- getLoaderManager().restartLoader(0, null /* args */, this /* callback */);
+ LoaderManager.getInstance(this).restartLoader(0, null /* args */, this /* callback */);
}
}
@@ -161,7 +161,8 @@ public class ContactResultsFragment extends Fragment implements
}
@Override
- public void onLoaderReset(Loader<Cursor> loader) {}
+ public void onLoaderReset(Loader<Cursor> loader) {
+ }
@Override
public void onDestroy() {
@@ -173,8 +174,9 @@ public class ContactResultsFragment extends Fragment implements
/**
* Creates a new instance of the {@link ContactResultsFragment}.
*
- * @param listener A scroll listener that will be notified when the list of search results has
- * been scrolled.
+ * @param listener A scroll listener that will be notified when the list of search
+ * results has
+ * been scrolled.
* @param initialSearchQuery An optional search query that will be inputted when the fragment
* starts up.
*/
diff --git a/src/com/android/car/dialer/ContactSearchActivity.java b/src/com/android/car/dialer/ContactSearchActivity.java
index 10d48d27..03243f36 100644
--- a/src/com/android/car/dialer/ContactSearchActivity.java
+++ b/src/com/android/car/dialer/ContactSearchActivity.java
@@ -18,13 +18,14 @@ package com.android.car.dialer;
import android.animation.ValueAnimator;
import android.app.Activity;
-import android.app.Fragment;
import android.app.SearchManager;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
@@ -37,7 +38,7 @@ import android.widget.EditText;
* An activity that manages contact searching. This activity will display the result of a search
* as well as show the details of a contact when that contact is clicked.
*/
-public class ContactSearchActivity extends Activity {
+public class ContactSearchActivity extends FragmentActivity {
private static final String CONTENT_FRAGMENT_TAG = "CONTENT_FRAGMENT_TAG";
private static final int ANIMATION_DURATION_MS = 100;
@@ -75,10 +76,12 @@ public class ContactSearchActivity extends Activity {
mSearchField.addTextChangedListener(new TextWatcher() {
@Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
@Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
@Override
public void afterTextChanged(Editable s) {
@@ -186,7 +189,7 @@ public class ContactSearchActivity extends Activity {
// changes since any lists in it will be reset to the top.
resetSearchPanelElevation();
- getFragmentManager().beginTransaction()
+ getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.animator.fade_in, R.animator.fade_out)
.replace(R.id.content_fragment_container, fragment, CONTENT_FRAGMENT_TAG)
.commitNow();
@@ -197,7 +200,7 @@ public class ContactSearchActivity extends Activity {
*/
@Nullable
private Fragment getCurrentFragment() {
- return getFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
+ return getSupportFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
}
@Override
diff --git a/src/com/android/car/dialer/TelecomActivity.java b/src/com/android/car/dialer/TelecomActivity.java
index 49de54c9..a4b8518c 100644
--- a/src/com/android/car/dialer/TelecomActivity.java
+++ b/src/com/android/car/dialer/TelecomActivity.java
@@ -35,6 +35,7 @@ import com.android.car.dialer.telecom.UiCall;
import com.android.car.dialer.telecom.UiCallManager;
import com.android.car.dialer.ui.CallHistoryFragment;
import com.android.car.dialer.ui.CallLogListingTask;
+import com.android.car.dialer.ui.ContactListFragment;
import java.util.List;
import java.util.stream.Stream;
@@ -296,9 +297,7 @@ public class TelecomActivity extends CarDrawerActivity implements CallListener {
Fragment fragment = DialerFragment.newInstance(dialNumber);
// Add the dialer fragment to the backstack so that it can be popped off to dismiss it.
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.content_fragment_container, fragment, DIALER_FRAGMENT_TAG)
- .commit();
+ setContentFragment(fragment);
}
/**
@@ -349,6 +348,7 @@ public class TelecomActivity extends CarDrawerActivity implements CallListener {
}
maybeHideDialer();
+
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(enter, exit)
.replace(R.id.content_fragment_container, fragment, CONTENT_FRAGMENT_TAG)
@@ -484,9 +484,10 @@ public class TelecomActivity extends CarDrawerActivity implements CallListener {
private static final int ITEM_FAVORITES = 0;
private static final int ITEM_CALLLOG_ALL = 1;
private static final int ITEM_CALLLOG_MISSED = 2;
- private static final int ITEM_DIAL = 3;
+ private static final int ITEM_CONTACT = 3;
+ private static final int ITEM_DIAL = 4;
- private static final int ITEM_COUNT = 4;
+ private static final int ITEM_COUNT = 5;
DialerRootAdapter() {
super(TelecomActivity.this, false /* showDisabledListOnEmpty */);
@@ -519,6 +520,10 @@ public class TelecomActivity extends CarDrawerActivity implements CallListener {
textResId = R.string.calllog_favorites;
iconResId = R.drawable.ic_favorite;
break;
+ case ITEM_CONTACT:
+ textResId = R.string.contact_menu_label;
+ iconResId = R.drawable.ic_contact;
+ break;
default:
Log.wtf(TAG, "Unexpected position: " + position);
return;
@@ -545,6 +550,9 @@ public class TelecomActivity extends CarDrawerActivity implements CallListener {
case ITEM_FAVORITES:
showSpeedDialFragment();
break;
+ case ITEM_CONTACT:
+ showContact();
+ break;
default:
Log.w(TAG, "Invalid position in ROOT menu! " + position);
}
@@ -552,9 +560,10 @@ public class TelecomActivity extends CarDrawerActivity implements CallListener {
}
private void showCallHistory(@PhoneLoader.CallType int callType) {
- Fragment fragment = CallHistoryFragment.newInstance(callType);
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.content_fragment_container, fragment)
- .commit();
+ setContentFragment(CallHistoryFragment.newInstance(callType));
+ }
+
+ private void showContact() {
+ setContentFragment(ContactListFragment.newInstance());
}
}
diff --git a/src/com/android/car/dialer/ui/CallHistoryListItemProvider.java b/src/com/android/car/dialer/ui/CallHistoryListItemProvider.java
index 2b905efa..6dc0c3d4 100644
--- a/src/com/android/car/dialer/ui/CallHistoryListItemProvider.java
+++ b/src/com/android/car/dialer/ui/CallHistoryListItemProvider.java
@@ -22,7 +22,7 @@ import androidx.car.widget.ListItem;
import androidx.car.widget.ListItemProvider;
import androidx.car.widget.TextListItem;
-import com.android.car.dialer.ui.listitem.CallLogListItem;
+import com.android.car.dialer.telecom.UiCallManager;
import java.util.ArrayList;
import java.util.List;
@@ -34,7 +34,16 @@ public class CallHistoryListItemProvider extends ListItemProvider {
public void setCallHistoryListItems(Context context,
List<CallLogListingTask.CallLogItem> items) {
for (CallLogListingTask.CallLogItem callLogItem : items) {
- mItems.add(new CallLogListItem(context, callLogItem));
+ TextListItem callLogListItem = new TextListItem(context);
+
+ callLogListItem.setPrimaryActionIcon(
+ new BitmapDrawable(context.getResources(), callLogItem.mIcon), true);
+ callLogListItem.setTitle(callLogItem.mTitle);
+ callLogListItem.setBody(callLogItem.mText);
+ callLogListItem.setOnClickListener(
+ (v) -> UiCallManager.get().safePlaceCall(callLogItem.mNumber, false));
+
+ mItems.add(callLogListItem);
}
}
diff --git a/src/com/android/car/dialer/ui/ContactListFragment.java b/src/com/android/car/dialer/ui/ContactListFragment.java
new file mode 100644
index 00000000..1d265cb0
--- /dev/null
+++ b/src/com/android/car/dialer/ui/ContactListFragment.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.car.dialer.ui;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.car.widget.AlphaJumpBucketer;
+import androidx.car.widget.IAlphaJumpAdapter;
+import androidx.car.widget.ListItemAdapter;
+import androidx.car.widget.PagedListView;
+
+import com.android.car.dialer.ContactDetailsFragment;
+import com.android.car.dialer.R;
+import com.android.car.dialer.telecom.PhoneLoader;
+import com.android.car.dialer.telecom.TelecomUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Contact Fragment.
+ */
+public class ContactListFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>,
+ ContactListItemProvider.OnShowContactDetailListener {
+ private static final int CONTACT_LOADER_ID = 1;
+
+ private PagedListView mPagedListView;
+
+ public static ContactListFragment newInstance() {
+ ContactListFragment fragment = new ContactListFragment();
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LoaderManager loaderManager = LoaderManager.getInstance(this);
+ loaderManager.initLoader(CONTACT_LOADER_ID, null, this);
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View fragmentView = inflater.inflate(R.layout.contact_list_fragment, container, false);
+ mPagedListView = fragmentView.findViewById(R.id.list_view);
+ return fragmentView;
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int i, @Nullable Bundle bundle) {
+ return new CursorLoader(
+ getContext(),
+ ContactsContract.Data.CONTENT_URI,
+ null,
+ ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Phone
+ .CONTENT_ITEM_TYPE + "'",
+ null,
+ ContactsContract.Contacts.DISPLAY_NAME + " ASC "
+ );
+ }
+
+ @Override
+ public void onLoadFinished(@NonNull Loader loader, Cursor cursor) {
+ List<ContactItem> contactItems = new ArrayList<>();
+ while (cursor.moveToNext()) {
+ String number = PhoneLoader.getPhoneNumber(cursor, getContext().getContentResolver());
+
+ int idColumnIndex = PhoneLoader.getIdColumnIndex(cursor);
+ int id = cursor.getInt(idColumnIndex);
+
+ int displayNameColumnIndex = cursor.getColumnIndex(
+ ContactsContract.Contacts.DISPLAY_NAME);
+ String displayName = cursor.getString(displayNameColumnIndex);
+
+ int lookupKeyColumnIndex = cursor.getColumnIndex(
+ ContactsContract.Contacts.LOOKUP_KEY);
+ String lookupKey = cursor.getString(lookupKeyColumnIndex);
+
+ contactItems.add(new ContactItem(number, id, displayName, null, lookupKey));
+ }
+
+ ContactListAdapter contactListAdapter = new ContactListAdapter(getContext(),
+ contactItems);
+ mPagedListView.setAdapter(contactListAdapter);
+ contactListAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onLoaderReset(@NonNull Loader loader) {
+ }
+
+ @Override
+ public void onShowContactDetail(int contactId, String lookupKey) {
+ View contactDetailContainer =
+ getView().findViewById(R.id.contact_detail_container);
+ contactDetailContainer.setVisibility(View.VISIBLE);
+ setActivityActionBarVisibility(View.GONE);
+
+ final Uri uri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
+ Fragment contactDetailFragment = ContactDetailsFragment.newInstance(uri, null);
+ getChildFragmentManager().beginTransaction().replace(R.id.contact_detail_fragment_container,
+ contactDetailFragment).commit();
+
+ getView().findViewById(R.id.back_button).setOnClickListener((v) -> {
+ getChildFragmentManager().beginTransaction().remove(contactDetailFragment).commit();
+ contactDetailContainer.setVisibility(View.GONE);
+ setActivityActionBarVisibility(View.VISIBLE);
+ });
+
+ }
+
+ private void setActivityActionBarVisibility(int visibility) {
+ View actionBar = getActivity().getWindow().getDecorView().findViewById(R.id.car_toolbar);
+ if (actionBar != null) {
+ actionBar.setVisibility(visibility);
+ }
+ }
+
+ /**
+ * Pojo which holds a contact entry information.
+ */
+ public static class ContactItem {
+ public final String mNumber;
+ public final int mId;
+ public final String mDisplayName;
+ public final Bitmap mIcon;
+ public final String mLookupKey;
+
+ private ContactItem(String number, int id, String displayName, Bitmap icon,
+ String lookupKey) {
+ mNumber = number;
+ mId = id;
+ mDisplayName = displayName;
+ mIcon = icon;
+ mLookupKey = lookupKey;
+ }
+ }
+
+ private class ContactListAdapter extends ListItemAdapter implements IAlphaJumpAdapter {
+
+ List<ContactItem> mContactItems;
+
+ public ContactListAdapter(Context context,
+ List<ContactItem> contactItems) {
+ super(context,
+ new ContactListItemProvider(context, contactItems, ContactListFragment.this));
+ mContactItems = contactItems;
+ }
+
+ public ContactListAdapter(Context context, List<ContactItem> contactItems,
+ int backgroundStyle) {
+ super(context,
+ new ContactListItemProvider(context, contactItems, ContactListFragment.this),
+ backgroundStyle);
+ mContactItems = contactItems;
+ }
+
+ @Override
+ public Collection<Bucket> getAlphaJumpBuckets() {
+ AlphaJumpBucketer alphaJumpBucketer = new AlphaJumpBucketer();
+ List<String> values = new ArrayList<>();
+ for (ContactItem contactItem : mContactItems) {
+ values.add(contactItem.mDisplayName);
+ }
+
+ return alphaJumpBucketer.createBuckets(values.toArray(new String[]{}));
+ }
+
+ @Override
+ public void onAlphaJumpEnter() {
+ }
+
+ @Override
+ public void onAlphaJumpLeave(Bucket bucket) {
+ }
+ }
+}
diff --git a/src/com/android/car/dialer/ui/ContactListItemProvider.java b/src/com/android/car/dialer/ui/ContactListItemProvider.java
new file mode 100644
index 00000000..890309ca
--- /dev/null
+++ b/src/com/android/car/dialer/ui/ContactListItemProvider.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.car.dialer.ui;
+
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+
+import androidx.car.widget.ListItem;
+import androidx.car.widget.ListItemProvider;
+import androidx.car.widget.TextListItem;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.android.car.dialer.R;
+import com.android.car.dialer.telecom.UiCallManager;
+import com.android.car.dialer.ui.listitem.ContactListItem;
+
+/**
+ * Provides ListItem for contact list.
+ */
+public class ContactListItemProvider extends ListItemProvider {
+
+ private final List<TextListItem> mItems = new ArrayList<>();
+ private final OnShowContactDetailListener mOnShowContactDetailListener;
+
+ public interface OnShowContactDetailListener {
+ void onShowContactDetail(int contactId, String lookupKey);
+ }
+
+ public ContactListItemProvider(Context context, List<ContactListFragment.ContactItem> items,
+ OnShowContactDetailListener onShowContactDetailListener) {
+ mOnShowContactDetailListener = onShowContactDetailListener;
+ for (ContactListFragment.ContactItem contactItem : items) {
+ ContactListItem textListItem = new ContactListItem(context, contactItem);
+ textListItem.setPrimaryActionIcon(
+ new BitmapDrawable(context.getResources(), contactItem.mIcon), true);
+ textListItem.setTitle(contactItem.mDisplayName);
+ textListItem.setOnClickListener(
+ (v) -> UiCallManager.get().safePlaceCall(contactItem.mNumber, true));
+ textListItem.setSupplementalIcon(R.drawable.ic_contact, true, (v) -> {
+ mOnShowContactDetailListener.onShowContactDetail(contactItem.mId,
+ contactItem.mLookupKey);
+ });
+ mItems.add(textListItem);
+ }
+ }
+
+ @Override
+ public ListItem get(int position) {
+ return mItems.get(position);
+ }
+
+ @Override
+ public int size() {
+ return mItems.size();
+ }
+}
diff --git a/src/com/android/car/dialer/ui/listitem/CallLogListItem.java b/src/com/android/car/dialer/ui/listitem/CallLogListItem.java
deleted file mode 100644
index c0cb4143..00000000
--- a/src/com/android/car/dialer/ui/listitem/CallLogListItem.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.car.dialer.ui.listitem;
-
-import android.content.Context;
-import android.graphics.drawable.BitmapDrawable;
-
-import androidx.car.widget.TextListItem;
-
-import com.android.car.dialer.telecom.UiCallManager;
-import com.android.car.dialer.ui.CallHistoryListItemProvider;
-import com.android.car.dialer.ui.CallLogListingTask;
-
-/**
- * List item which is created by {@link CallHistoryListItemProvider} binds a call list item to a
- * list view item.
- */
-public class CallLogListItem extends TextListItem {
- private final CallLogListingTask.CallLogItem mCallLogItem;
- private final Context mContext;
-
- public CallLogListItem(Context context, CallLogListingTask.CallLogItem callLog) {
- super(context);
- mCallLogItem = callLog;
- mContext = context;
- }
-
- @Override
- public void onBind(ViewHolder viewHolder) {
- super.onBind(viewHolder);
- setPrimaryActionIcon(
- new BitmapDrawable(mContext.getResources(), mCallLogItem.mIcon), true);
- setTitle(mCallLogItem.mTitle);
- setBody(mCallLogItem.mText);
-
- viewHolder.itemView.setOnClickListener((v) -> {
- UiCallManager.get().safePlaceCall(mCallLogItem.mNumber, false);
- });
- }
-}
diff --git a/src/com/android/car/dialer/ui/listitem/ContactListItem.java b/src/com/android/car/dialer/ui/listitem/ContactListItem.java
new file mode 100644
index 00000000..03c5575b
--- /dev/null
+++ b/src/com/android/car/dialer/ui/listitem/ContactListItem.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.car.dialer.ui.listitem;
+
+import android.content.Context;
+
+import androidx.car.widget.TextListItem;
+
+import com.android.car.dialer.telecom.TelecomUtils;
+import com.android.car.dialer.ui.ContactListFragment;
+
+/**
+ * ListItem for contact.
+ */
+public class ContactListItem extends TextListItem {
+ private Context mContext;
+ private ContactListFragment.ContactItem mContactItem;
+
+ public ContactListItem(Context context, ContactListFragment.ContactItem contactItem) {
+ super(context);
+ mContext = context;
+ mContactItem = contactItem;
+ }
+
+ @Override
+ public void onBind(ViewHolder viewHolder) {
+ super.onBind(viewHolder);
+ TelecomUtils.setContactBitmapAsync(mContext, viewHolder.getPrimaryIcon(),
+ mContactItem.mDisplayName, mContactItem.mNumber);
+ }
+}