summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYorke Lee <yorkelee@google.com>2015-07-15 22:40:04 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-07-15 22:40:04 +0000
commit3abaae1a037f1764b4329dd6381b4c9e6ffa952a (patch)
tree4687a00a9b56a8c8e85c5291eaf11c32befd9baa
parent55fcb21595a4702029eb5695862ca2726f248649 (diff)
parent38019af70eb1ca084d36291390bbc54dc81027de (diff)
downloadpackages_apps_Dialer-3abaae1a037f1764b4329dd6381b4c9e6ffa952a.tar.gz
packages_apps_Dialer-3abaae1a037f1764b4329dd6381b4c9e6ffa952a.tar.bz2
packages_apps_Dialer-3abaae1a037f1764b4329dd6381b4c9e6ffa952a.zip
am 38019af7: Update Dialer UI to prompt for permissions
* commit '38019af70eb1ca084d36291390bbc54dc81027de': Update Dialer UI to prompt for permissions
-rw-r--r--res/layout/call_log_fragment.xml3
-rw-r--r--res/layout/empty_content_view.xml (renamed from res/layout/empty_list_view.xml)28
-rw-r--r--res/layout/show_all_contacts_fragment.xml3
-rw-r--r--res/layout/speed_dial_fragment.xml3
-rw-r--r--res/values/styles.xml10
-rw-r--r--src/com/android/dialer/DialtactsActivity.java21
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java95
-rw-r--r--src/com/android/dialer/list/AllContactsFragment.java60
-rw-r--r--src/com/android/dialer/list/EmptyContactsListAdapter.java47
-rw-r--r--src/com/android/dialer/list/SpeedDialFragment.java37
-rw-r--r--src/com/android/dialer/util/DialerUtils.java22
-rw-r--r--src/com/android/dialer/widget/EmptyContentView.java102
12 files changed, 317 insertions, 114 deletions
diff --git a/res/layout/call_log_fragment.xml b/res/layout/call_log_fragment.xml
index 68e306074..3a7013d57 100644
--- a/res/layout/call_log_fragment.xml
+++ b/res/layout/call_log_fragment.xml
@@ -27,11 +27,10 @@
android:paddingStart="@dimen/call_log_horizontal_margin"
android:paddingEnd="@dimen/call_log_horizontal_margin" />
- <include
+ <com.android.dialer.widget.EmptyContentView
android:id="@+id/empty_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- layout="@layout/empty_list_view"
android:visibility="gone" />
</FrameLayout>
diff --git a/res/layout/empty_list_view.xml b/res/layout/empty_content_view.xml
index 7f961a350..18633d0f9 100644
--- a/res/layout/empty_list_view.xml
+++ b/res/layout/empty_content_view.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2015 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.
@@ -13,15 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingTop="@dimen/empty_list_message_top_padding"
- android:paddingBottom="@dimen/actionbar_and_tab_height"
- android:minHeight="?android:attr/listPreferredItemHeight">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/emptyListViewImage"
android:layout_height="wrap_content"
@@ -39,4 +32,19 @@
android:paddingRight="16dp"
android:paddingLeft="16dp" />
-</LinearLayout>
+ <TextView
+ android:id="@+id/emptyListViewAction"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_gravity="center_horizontal"
+ android:paddingRight="16dp"
+ android:paddingLeft="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="@string/permission_single_turn_on"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="true"
+ style="@style/TextActionStyle" />
+
+</merge>
diff --git a/res/layout/show_all_contacts_fragment.xml b/res/layout/show_all_contacts_fragment.xml
index 00358dc47..3b501fb88 100644
--- a/res/layout/show_all_contacts_fragment.xml
+++ b/res/layout/show_all_contacts_fragment.xml
@@ -44,11 +44,10 @@
android:nestedScrollingEnabled="true" />
</FrameLayout>
- <include
+ <com.android.dialer.widget.EmptyContentView
android:id="@+id/empty_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- layout="@layout/empty_list_view"
android:visibility="gone"/>
</LinearLayout>
diff --git a/res/layout/speed_dial_fragment.xml b/res/layout/speed_dial_fragment.xml
index 18820497e..55dd158d2 100644
--- a/res/layout/speed_dial_fragment.xml
+++ b/res/layout/speed_dial_fragment.xml
@@ -41,11 +41,10 @@
android:nestedScrollingEnabled="true" />
</FrameLayout>
- <include
+ <com.android.dialer.widget.EmptyContentView
android:id="@+id/empty_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- layout="@layout/empty_list_view"
android:visibility="gone"/>
</FrameLayout>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 957fabf86..e3a2f9974 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -218,20 +218,24 @@
<item name="cardBackgroundColor">@color/background_dialer_call_log_list_item</item>
</style>
- <style name="PromoCardActionStyle">
+ <style name="TextActionStyle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">@dimen/call_log_action_height</item>
<item name="android:gravity">end|center_vertical</item>
<item name="android:paddingStart">@dimen/call_log_action_horizontal_padding</item>
<item name="android:paddingEnd">@dimen/call_log_action_horizontal_padding</item>
- <item name="android:textColor">@color/promo_card_text</item>
- <item name="android:textSize">@dimen/call_log_list_item_actions_text_size</item>
+ <item name="android:textColor">@color/dialtacts_theme_color</item>
<item name="android:fontFamily">"sans-serif-medium"</item>
<item name="android:focusable">true</item>
<item name="android:singleLine">true</item>
<item name="android:textAllCaps">true</item>
</style>
+ <style name="PromoCardActionStyle" parent="TextActionStyle">
+ <item name="android:textColor">@color/promo_card_text</item>
+ <item name="android:textSize">@dimen/call_log_list_item_actions_text_size</item>
+ </style>
+
<style name="VoicemailPlaybackLayoutTextStyle">
<item name="android:textSize">14sp</item>
</style>
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 31d1b94bf..85197a530 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -66,6 +66,7 @@ import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.common.widget.FloatingActionButtonController;
import com.android.contacts.commonbind.analytics.AnalyticsUtil;
import com.android.dialer.calllog.CallLogActivity;
+import com.android.dialer.calllog.CallLogFragment;
import com.android.dialer.database.DialerDatabaseHelper;
import com.android.dialer.dialpad.DialpadFragment;
import com.android.dialer.dialpad.SmartDialNameMatcher;
@@ -101,6 +102,7 @@ import java.util.List;
public class DialtactsActivity extends TransactionSafeActivity implements View.OnClickListener,
DialpadFragment.OnDialpadQueryChangedListener,
OnListFragmentScrolledListener,
+ CallLogFragment.HostInterface,
ListsFragment.HostInterface,
SpeedDialFragment.HostInterface,
SearchFragment.HostInterface,
@@ -1207,6 +1209,24 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
mListsFragment.getRemoveView().setDragDropController(dragController);
}
+ /**
+ * Implemented to satisfy {@link SpeedDialFragment.HostInterface}
+ */
+ @Override
+ public void showAllContactsTab() {
+ if (mListsFragment != null) {
+ mListsFragment.showTab(ListsFragment.TAB_INDEX_ALL_CONTACTS);
+ }
+ }
+
+ /**
+ * Implemented to satisfy {@link CallLogFragment.HostInterface}
+ */
+ @Override
+ public void showDialpad() {
+ showDialpadFragment(true);
+ }
+
@Override
public void onPickPhoneNumberAction(Uri dataUri) {
// Specify call-origin so that users will see the previous tab instead of
@@ -1322,7 +1342,6 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
return mActionBarHeight;
}
-
private int getFabAlignment() {
if (!mIsLandscape && !isInSearchUi() &&
mListsFragment.getCurrentTabIndex() == ListsFragment.TAB_INDEX_SPEED_DIAL) {
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 5d7c408ce..d1a9827eb 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -16,6 +16,8 @@
package com.android.dialer.calllog;
+import static android.Manifest.permission.READ_CALL_LOG;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -26,6 +28,7 @@ import android.app.KeyguardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Rect;
@@ -46,6 +49,7 @@ import android.widget.ListView;
import android.widget.TextView;
import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.common.util.ViewUtil;
import com.android.dialer.R;
import com.android.dialer.list.ListsFragment.HostInterface;
@@ -55,6 +59,8 @@ import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
import com.android.dialer.voicemail.VoicemailStatusHelper;
import com.android.dialer.voicemail.VoicemailStatusHelper.StatusMessage;
import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
+import com.android.dialer.widget.EmptyContentView;
+import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener;
import com.android.dialerbind.ObjectFactory;
import java.util.List;
@@ -63,8 +69,8 @@ import java.util.List;
* Displays a list of call log entries. To filter for a particular kind of call
* (all, missed or voicemails), specify it in the constructor.
*/
-public class CallLogFragment extends Fragment
- implements CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher {
+public class CallLogFragment extends Fragment implements CallLogQueryHandler.Listener,
+ CallLogAdapter.CallFetcher, OnEmptyViewActionButtonClickedListener {
private static final String TAG = "CallLogFragment";
/**
@@ -81,6 +87,8 @@ public class CallLogFragment extends Fragment
// No date-based filtering.
private static final int NO_DATE_LIMIT = 0;
+ private static final int READ_CALL_LOG_PERMISSION_REQUEST_CODE = 1;
+
private RecyclerView mRecyclerView;
private LinearLayoutManager mLayoutManager;
private CallLogAdapter mAdapter;
@@ -91,7 +99,7 @@ public class CallLogFragment extends Fragment
/** Whether there is at least one voicemail source installed. */
private boolean mVoicemailSourcesAvailable = false;
- private View mEmptyListView;
+ private EmptyContentView mEmptyListView;
private KeyguardManager mKeyguardManager;
private boolean mEmptyLoaderRunning;
@@ -116,6 +124,8 @@ public class CallLogFragment extends Fragment
private final ContentObserver mVoicemailStatusObserver = new CustomContentObserver();
private boolean mRefreshDataRequired = true;
+ private boolean mHasReadCallLogPermission = false;
+
// Exactly same variable is in Fragment as a package private.
private boolean mMenuVisible = true;
@@ -130,6 +140,16 @@ public class CallLogFragment extends Fragment
// the date filter are included. If zero, no date-based filtering occurs.
private long mDateLimit = NO_DATE_LIMIT;
+ /*
+ * True if this instance of the CallLogFragment is the Recents screen shown in
+ * DialtactsActivity.
+ */
+ private boolean mIsRecentsFragment;
+
+ public interface HostInterface {
+ public void showDialpad();
+ }
+
public CallLogFragment() {
this(CallLogQueryHandler.CALL_TYPE_ALL, NO_LOG_LIMIT);
}
@@ -139,9 +159,7 @@ public class CallLogFragment extends Fragment
}
public CallLogFragment(int filterType, int logLimit) {
- super();
- mCallTypeFilter = filterType;
- mLogLimit = logLimit;
+ this(filterType, logLimit, NO_DATE_LIMIT);
}
/**
@@ -162,7 +180,8 @@ public class CallLogFragment extends Fragment
* @param dateLimit limits results to calls occurring on or after the specified date.
*/
public CallLogFragment(int filterType, int logLimit, long dateLimit) {
- this(filterType, logLimit);
+ mCallTypeFilter = filterType;
+ mLogLimit = logLimit;
mDateLimit = dateLimit;
}
@@ -175,6 +194,8 @@ public class CallLogFragment extends Fragment
mDateLimit = state.getLong(KEY_DATE_LIMIT, mDateLimit);
}
+ mIsRecentsFragment = mLogLimit != NO_LOG_LIMIT;
+
final Activity activity = getActivity();
final ContentResolver resolver = activity.getContentResolver();
String currentCountryIso = GeoUtil.getCurrentCountryIso(activity);
@@ -268,7 +289,9 @@ public class CallLogFragment extends Fragment
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
- mEmptyListView = view.findViewById(R.id.empty_list_view);
+ mEmptyListView = (EmptyContentView) view.findViewById(R.id.empty_list_view);
+ mEmptyListView.setImage(R.drawable.empty_call_log);
+ mEmptyListView.setActionClickedListener(this);
String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
boolean isShowingRecentsTab = mLogLimit != NO_LOG_LIMIT || mDateLimit != NO_DATE_LIMIT;
@@ -287,7 +310,6 @@ public class CallLogFragment extends Fragment
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
-
updateEmptyMessage(mCallTypeFilter);
mAdapter.onRestoreInstanceState(savedInstanceState);
}
@@ -305,6 +327,16 @@ public class CallLogFragment extends Fragment
@Override
public void onResume() {
super.onResume();
+ final boolean hasReadCallLogPermission =
+ PermissionsUtil.hasPermission(getActivity(), READ_CALL_LOG);
+ if (!mHasReadCallLogPermission && hasReadCallLogPermission) {
+ // We didn't have the permission before, and now we do. Force a refresh of the call log.
+ // Note that this code path always happens on a fresh start, but mRefreshDataRequired
+ // is already true in that case anyway.
+ mRefreshDataRequired = true;
+ updateEmptyMessage(mCallTypeFilter);
+ }
+ mHasReadCallLogPermission = hasReadCallLogPermission;
refreshData();
}
@@ -359,6 +391,17 @@ public class CallLogFragment extends Fragment
}
private void updateEmptyMessage(int filterType) {
+ final Context context = getActivity();
+ if (context == null) {
+ return;
+ }
+
+ if (!PermissionsUtil.hasPermission(context, READ_CALL_LOG)) {
+ mEmptyListView.setDescription(R.string.permission_no_calllog);
+ mEmptyListView.setActionLabel(R.string.permission_single_turn_on);
+ return;
+ }
+
final int messageId;
switch (filterType) {
case Calls.MISSED_TYPE:
@@ -374,8 +417,12 @@ public class CallLogFragment extends Fragment
throw new IllegalArgumentException("Unexpected filter type in CallLogFragment: "
+ filterType);
}
- DialerUtils.configureEmptyListView(
- mEmptyListView, R.drawable.empty_call_log, messageId, getResources());
+ mEmptyListView.setDescription(messageId);
+ if (mIsRecentsFragment) {
+ mEmptyListView.setActionLabel(R.string.recentCalls_empty_action);
+ } else {
+ mEmptyListView.setActionLabel(EmptyContentView.NO_LABEL);
+ }
}
CallLogAdapter getAdapter() {
@@ -437,4 +484,30 @@ public class CallLogFragment extends Fragment
CallLogNotificationsHelper.updateVoicemailNotifications(getActivity());
}
}
+
+ @Override
+ public void onEmptyViewActionButtonClicked(String[] permissions) {
+ final Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ if (!PermissionsUtil.hasPermission(activity, READ_CALL_LOG)) {
+ requestPermissions(new String[] {READ_CALL_LOG}, READ_CALL_LOG_PERMISSION_REQUEST_CODE);
+ } else if (mIsRecentsFragment) {
+ // Show dialpad if we are the recents fragment.
+ ((HostInterface) activity).showDialpad();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (requestCode == READ_CALL_LOG_PERMISSION_REQUEST_CODE) {
+ if (grantResults.length >= 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
+ // Force a refresh of the data since we were missing the permission before this.
+ mRefreshDataRequired = true;
+ }
+ }
+ }
}
diff --git a/src/com/android/dialer/list/AllContactsFragment.java b/src/com/android/dialer/list/AllContactsFragment.java
index d34250b48..00b629c2b 100644
--- a/src/com/android/dialer/list/AllContactsFragment.java
+++ b/src/com/android/dialer/list/AllContactsFragment.java
@@ -16,7 +16,11 @@
package com.android.dialer.list;
+import static android.Manifest.permission.READ_CONTACTS;
+
+import android.app.Activity;
import android.content.Loader;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -34,13 +38,19 @@ import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.common.util.ViewUtil;
import com.android.dialer.R;
import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.IntentUtil;
+import com.android.dialer.widget.EmptyContentView;
+import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener;
/**
* Fragments to show all contacts with phone numbers.
*/
-public class AllContactsFragment extends ContactEntryListFragment<ContactEntryListAdapter> {
+public class AllContactsFragment extends ContactEntryListFragment<ContactEntryListAdapter>
+ implements OnEmptyViewActionButtonClickedListener {
+
+ private static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1;
- private View mEmptyListView;
+ private EmptyContentView mEmptyListView;
public AllContactsFragment() {
setQuickContactEnabled(false);
@@ -55,9 +65,10 @@ public class AllContactsFragment extends ContactEntryListFragment<ContactEntryLi
public void onViewCreated(View view, android.os.Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- mEmptyListView = view.findViewById(R.id.empty_list_view);
- DialerUtils.configureEmptyListView(mEmptyListView, R.drawable.empty_contacts,
- R.string.all_contacts_empty, getResources());
+ mEmptyListView = (EmptyContentView) view.findViewById(R.id.empty_list_view);
+ mEmptyListView.setImage(R.drawable.empty_contacts);
+ mEmptyListView.setDescription(R.string.all_contacts_empty);
+ mEmptyListView.setActionClickedListener(this);
getListView().setEmptyView(mEmptyListView);
mEmptyListView.setVisibility(View.GONE);
@@ -66,8 +77,14 @@ public class AllContactsFragment extends ContactEntryListFragment<ContactEntryLi
@Override
protected void startLoading() {
- if (PermissionsUtil.hasContactsPermissions(getActivity())) {
+ if (PermissionsUtil.hasPermission(getActivity(), READ_CONTACTS)) {
super.startLoading();
+ mEmptyListView.setDescription(R.string.all_contacts_empty);
+ mEmptyListView.setActionLabel(R.string.all_contacts_empty_add_contact_action);
+ } else {
+ mEmptyListView.setDescription(R.string.permission_no_contacts);
+ mEmptyListView.setActionLabel(R.string.permission_single_turn_on);
+ mEmptyListView.setVisibility(View.VISIBLE);
}
}
@@ -82,10 +99,6 @@ public class AllContactsFragment extends ContactEntryListFragment<ContactEntryLi
@Override
protected ContactEntryListAdapter createListAdapter() {
- if (!PermissionsUtil.hasContactsPermissions(getActivity())) {
- return new EmptyContactsListAdapter(getActivity());
- }
-
final DefaultContactListAdapter adapter = new DefaultContactListAdapter(getActivity()) {
@Override
protected void bindView(View itemView, int partition, Cursor cursor, int position) {
@@ -118,4 +131,31 @@ public class AllContactsFragment extends ContactEntryListFragment<ContactEntryLi
protected void onItemClick(int position, long id) {
// Do nothing. Implemented to satisfy ContactEntryListFragment.
}
+
+ @Override
+ public void onEmptyViewActionButtonClicked(String[] permissions) {
+ final Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ if (!PermissionsUtil.hasPermission(activity, READ_CONTACTS)) {
+ requestPermissions(new String[] {READ_CONTACTS}, READ_CONTACTS_PERMISSION_REQUEST_CODE);
+ } else {
+ // Add new contact
+ DialerUtils.startActivityWithErrorToast(activity, IntentUtil.getNewContactIntent(),
+ R.string.add_contact_not_available);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (requestCode == READ_CONTACTS_PERMISSION_REQUEST_CODE) {
+ if (grantResults.length >= 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
+ // Force a refresh of the data since we were missing the permission before this.
+ reloadData();
+ }
+ }
+ }
}
diff --git a/src/com/android/dialer/list/EmptyContactsListAdapter.java b/src/com/android/dialer/list/EmptyContactsListAdapter.java
deleted file mode 100644
index 54bd4771f..000000000
--- a/src/com/android/dialer/list/EmptyContactsListAdapter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2015 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.dialer.list;
-
-import android.content.Context;
-import android.content.CursorLoader;
-
-import com.android.contacts.common.list.ContactEntryListAdapter;
-
-/**
- * Used to display an empty contact list when we don't have the permissions to read contacts.
- */
-public class EmptyContactsListAdapter extends ContactEntryListAdapter {
-
- public EmptyContactsListAdapter(Context context) {
- super(context);
- }
-
- @Override
- public String getContactDisplayName(int position) {
- return null;
- }
-
- @Override
- public void configureLoader(CursorLoader loader, long directoryId) {
- loader.setUri(null);
- }
-
- @Override
- public int getCount() {
- return 0;
- }
-}
diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java
index bf9575858..aead1c81b 100644
--- a/src/com/android/dialer/list/SpeedDialFragment.java
+++ b/src/com/android/dialer/list/SpeedDialFragment.java
@@ -15,6 +15,8 @@
*/
package com.android.dialer.list;
+import static android.Manifest.permission.READ_CONTACTS;
+
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -50,6 +52,7 @@ import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.dialer.R;
import com.android.dialer.util.DialerUtils;
+import com.android.dialer.widget.EmptyContentView;
import java.util.ArrayList;
import java.util.HashMap;
@@ -58,7 +61,8 @@ import java.util.HashMap;
* This fragment displays the user's favorite/frequent contacts in a grid.
*/
public class SpeedDialFragment extends Fragment implements OnItemClickListener,
- PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener {
+ PhoneFavoritesTileAdapter.OnDataSetChangedForAnimationListener,
+ EmptyContentView.OnEmptyViewActionButtonClickedListener {
/**
* By default, the animation code assumes that all items in a list view are of the same height
@@ -81,6 +85,7 @@ public class SpeedDialFragment extends Fragment implements OnItemClickListener,
public interface HostInterface {
public void setDragDropController(DragDropController controller);
+ public void showAllContactsTab();
}
private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
@@ -157,7 +162,7 @@ public class SpeedDialFragment extends Fragment implements OnItemClickListener,
/**
* Layout used when there are no favorites.
*/
- private View mEmptyView;
+ private EmptyContentView mEmptyView;
private final ContactTileView.Listener mContactTileAdapterListener =
new ContactTileAdapterListener();
@@ -197,9 +202,16 @@ public class SpeedDialFragment extends Fragment implements OnItemClickListener,
if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) {
getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null,
mContactTileLoaderListener);
+
} else {
getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE).forceLoad();
}
+
+ mEmptyView.setDescription(R.string.speed_dial_empty);
+ mEmptyView.setActionLabel(R.string.speed_dial_empty_add_favorite_action);
+ } else {
+ mEmptyView.setDescription(R.string.permission_no_speeddial);
+ mEmptyView.setActionLabel(R.string.permission_single_turn_on);
}
Trace.endSection();
}
@@ -221,9 +233,9 @@ public class SpeedDialFragment extends Fragment implements OnItemClickListener,
(ImageView) getActivity().findViewById(R.id.contact_tile_drag_shadow_overlay);
mListView.setDragShadowOverlay(dragShadowOverlay);
- mEmptyView = mParentView.findViewById(R.id.empty_list_view);
- DialerUtils.configureEmptyListView(
- mEmptyView, R.drawable.empty_speed_dial, R.string.speed_dial_empty, getResources());
+ mEmptyView = (EmptyContentView) mParentView.findViewById(R.id.empty_list_view);
+ mEmptyView.setImage(R.drawable.empty_speed_dial);
+ mEmptyView.setActionClickedListener(this);
mContactTileFrame = mParentView.findViewById(R.id.contact_tile_frame);
@@ -449,4 +461,19 @@ public class SpeedDialFragment extends Fragment implements OnItemClickListener,
public AbsListView getListView() {
return mListView;
}
+
+ @Override
+ public void onEmptyViewActionButtonClicked(String[] permissions) {
+ final Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
+ if (!PermissionsUtil.hasPermission(activity, READ_CONTACTS)) {
+ requestPermissions(new String[] {READ_CONTACTS}, 0);
+ } else {
+ // Switch tabs
+ ((HostInterface) activity).showAllContactsTab();
+ }
+ }
}
diff --git a/src/com/android/dialer/util/DialerUtils.java b/src/com/android/dialer/util/DialerUtils.java
index a44c2eec6..e25ada59d 100644
--- a/src/com/android/dialer/util/DialerUtils.java
+++ b/src/com/android/dialer/util/DialerUtils.java
@@ -40,6 +40,7 @@ import android.widget.Toast;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.interactions.TouchPointManager;
import com.android.dialer.R;
+import com.android.dialer.widget.EmptyContentView;
import com.android.incallui.CallCardFragment;
import com.android.incallui.Log;
@@ -116,27 +117,6 @@ public class DialerUtils {
}
/**
- * Sets the image asset and text for an empty list view (see empty_list_view.xml).
- *
- * @param emptyListView The empty list view.
- * @param imageResId The resource id for the drawable to set as the image.
- * @param strResId The resource id for the string to set as the message.
- * @param res The resources to obtain the image and string from.
- */
- public static void configureEmptyListView(
- View emptyListView, int imageResId, int strResId, Resources res) {
- ImageView emptyListViewImage =
- (ImageView) emptyListView.findViewById(R.id.emptyListViewImage);
-
- emptyListViewImage.setImageDrawable(res.getDrawable(imageResId));
- emptyListViewImage.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
-
- TextView emptyListViewMessage =
- (TextView) emptyListView.findViewById(R.id.emptyListViewMessage);
- emptyListViewMessage.setText(res.getString(strResId));
- }
-
- /**
* Closes an {@link AutoCloseable}, silently ignoring any checked exceptions. Does nothing if
* null.
*
diff --git a/src/com/android/dialer/widget/EmptyContentView.java b/src/com/android/dialer/widget/EmptyContentView.java
new file mode 100644
index 000000000..67c9ce15f
--- /dev/null
+++ b/src/com/android/dialer/widget/EmptyContentView.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 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.dialer.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.dialer.R;
+
+public class EmptyContentView extends LinearLayout implements View.OnClickListener {
+
+ public static final int NO_LABEL = 0;
+
+ private ImageView mImageView;
+ private TextView mDescriptionView;
+ private TextView mActionView;
+ private String[] mPermissions = new String[] {};
+ private OnEmptyViewActionButtonClickedListener mOnActionButtonClickedListener;
+
+ public interface OnEmptyViewActionButtonClickedListener {
+ public void onEmptyViewActionButtonClicked(String[] permissions);
+ }
+
+ public EmptyContentView(Context context) {
+ this(context, null);
+ }
+
+ public EmptyContentView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public EmptyContentView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public EmptyContentView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setOrientation(LinearLayout.VERTICAL);
+
+ final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.empty_content_view, this);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mImageView = (ImageView) findViewById(R.id.emptyListViewImage);
+ mDescriptionView = (TextView) findViewById(R.id.emptyListViewMessage);
+ mActionView = (TextView) findViewById(R.id.emptyListViewAction);
+ mActionView.setOnClickListener(this);
+ }
+
+ public void setDescription(int resourceId) {
+ mDescriptionView.setText(resourceId);
+ }
+
+ public void setImage(int resourceId) {
+ mImageView.setImageResource(resourceId);
+ }
+
+ public void setActionLabel(int resourceId) {
+ if (resourceId == NO_LABEL) {
+ mActionView.setText(null);
+ mActionView.setVisibility(View.GONE);
+ } else {
+ mActionView.setText(resourceId);
+ mActionView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public void setActionClickedListener(OnEmptyViewActionButtonClickedListener listener) {
+ mOnActionButtonClickedListener = listener;
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mOnActionButtonClickedListener != null) {
+ mOnActionButtonClickedListener.onEmptyViewActionButtonClicked(mPermissions);
+ }
+ }
+}