diff --git a/res/drawable/selectable_card.xml b/res/drawable/selectable_card.xml
new file mode 100644
index 00000000000..9c1987731b9
--- /dev/null
+++ b/res/drawable/selectable_card.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/res/layout/suggestion_tile_card.xml b/res/layout/suggestion_tile_card.xml
new file mode 100644
index 00000000000..6f94914e764
--- /dev/null
+++ b/res/layout/suggestion_tile_card.xml
@@ -0,0 +1,26 @@
+
+
+
+
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index e3e95be7f33..325df5b89fd 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -237,6 +237,7 @@ public class DashboardAdapter extends RecyclerView.Adapter {
+ View clickHandler = holder.itemView;
+ // If a view with @android:id/primary is defined, use that as the click handler
+ // instead.
+ final View primaryAction = holder.itemView.findViewById(android.R.id.primary);
+ if (primaryAction != null) {
+ clickHandler = primaryAction;
+ // set the item view to disabled to remove any touch effects
+ holder.itemView.setEnabled(false);
+ }
+ clickHandler.setOnClickListener(v -> {
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_SETTINGS_SUGGESTION, suggestionId);
((SettingsActivity) mContext).startSuggestion(suggestion.intent);
@@ -405,13 +415,18 @@ public class DashboardAdapter extends RecyclerView.Adapter
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index d7daa03a1fa..7b521138f6c 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -15,14 +15,32 @@
*/
package com.android.settings.dashboard;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.RuntimeEnvironment.application;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.view.ContextThemeWrapper;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
import android.widget.FrameLayout;
+import android.widget.RemoteViews;
+import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.conditional.Condition;
@@ -39,18 +57,13 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
@@ -62,7 +75,7 @@ import static org.mockito.Mockito.when;
public class DashboardAdapterTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
+ private SettingsActivity mContext;
@Mock
private View mView;
@Mock
@@ -109,7 +122,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_NotExpanded() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1", "pkg2", "pkg3"}));
+ setUpSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
verify(mFactory.metricsFeatureProvider, times(2)).action(
any(Context.class), mActionCategoryCaptor.capture(),
mActionPackageCaptor.capture());
@@ -124,7 +137,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_NotExpandedAndPaused() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1", "pkg2", "pkg3"}));
+ setUpSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onPause();
verify(mFactory.metricsFeatureProvider, times(4)).action(
any(Context.class), mActionCategoryCaptor.capture(),
@@ -141,7 +154,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_Expanded() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1", "pkg2", "pkg3"}));
+ setUpSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
@@ -160,7 +173,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedAndPaused() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1", "pkg2", "pkg3"}));
+ setUpSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
@@ -183,7 +196,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedAfterPause() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1", "pkg2", "pkg3"}));
+ setUpSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
@@ -208,7 +221,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedAfterPauseAndPausedAgain() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1", "pkg2", "pkg3"}));
+ setUpSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
@@ -237,7 +250,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShown() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1"}));
+ setUpSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
@@ -254,7 +267,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAndPaused() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1"}));
+ setUpSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
mSuggestionHolder.itemView.callOnClick();
@@ -273,7 +286,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAfterPause() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1"}));
+ setUpSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
@@ -293,7 +306,7 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionsLogs_ExpandedWithLessThanDefaultShownAfterPauseAndPausedAgain() {
- setUpSuggestions(makeSuggestions(new String[]{"pkg1"}));
+ setUpSuggestions(makeSuggestions("pkg1"));
mDashboardAdapter.onPause();
mDashboardAdapter.onBindSuggestionHeader(
mSuggestionHolder, mSuggestionHeaderData);
@@ -313,7 +326,54 @@ public class DashboardAdapterTest {
assertThat(mActionCategoryCaptor.getAllValues().toArray()).isEqualTo(expectedActions);
}
- private List makeSuggestions(String[] pkgNames) {
+ @Test
+ public void testBindViewHolder_inflateRemoteView() {
+ List packages = makeSuggestions("pkg1");
+ RemoteViews remoteViews = mock(RemoteViews.class);
+ TextView textView = new TextView(application);
+ doReturn(textView).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
+ packages.get(0).remoteViews = remoteViews;
+ mDashboardAdapter.setCategoriesAndSuggestions(Collections.emptyList(), packages);
+ mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
+ new FrameLayout(application),
+ R.layout.suggestion_tile_card);
+
+ mDashboardAdapter.onBindViewHolder(mSuggestionHolder, 1);
+ assertThat(textView.getParent()).isSameAs(mSuggestionHolder.itemView);
+ mSuggestionHolder.itemView.performClick();
+
+ verify(mContext).startSuggestion(any(Intent.class));
+ }
+
+ @Test
+ public void testBindViewHolder_primaryViewHandlesClick() {
+ Context context = new ContextThemeWrapper(application, R.style.Theme_Settings);
+
+ List packages = makeSuggestions("pkg1");
+ RemoteViews remoteViews = mock(RemoteViews.class);
+ FrameLayout layout = new FrameLayout(context);
+ Button primary = new Button(context);
+ primary.setId(android.R.id.primary);
+ layout.addView(primary);
+ doReturn(layout).when(remoteViews).apply(any(Context.class), any(ViewGroup.class));
+ packages.get(0).remoteViews = remoteViews;
+ mDashboardAdapter.setCategoriesAndSuggestions(Collections.emptyList(), packages);
+ mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
+ new FrameLayout(context),
+ R.layout.suggestion_tile_card);
+
+ mDashboardAdapter.onBindViewHolder(mSuggestionHolder, 1);
+
+ mSuggestionHolder.itemView.performClick();
+ assertThat(ShadowApplication.getInstance().getNextStartedActivity()).isNull();
+ verify(mContext, never()).startSuggestion(any(Intent.class));
+
+ primary.performClick();
+
+ verify(mContext).startSuggestion(any(Intent.class));
+ }
+
+ private List makeSuggestions(String... pkgNames) {
final List suggestions = new ArrayList<>();
for (String pkgName : pkgNames) {
Tile suggestion = new Tile();
@@ -327,7 +387,7 @@ public class DashboardAdapterTest {
private void setUpSuggestions(List suggestions) {
mDashboardAdapter.setCategoriesAndSuggestions(new ArrayList<>(), suggestions);
mSuggestionHolder = mDashboardAdapter.onCreateViewHolder(
- new FrameLayout(RuntimeEnvironment.application),
+ new FrameLayout(application),
mDashboardAdapter.getItemViewType(0));
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java
index 4a41ede188c..e85621e7b73 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java
@@ -85,6 +85,15 @@ public class SuggestionDismissControllerTest {
.isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);
}
+ @Test
+ public void getSwipeDirs_isSuggestionTileCard_shouldReturnDirection() {
+ final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
+ when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile_card);
+
+ assertThat(mController.getSwipeDirs(mRecyclerView, vh))
+ .isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);
+ }
+
@Test
public void getSwipeDirs_isNotSuggestionTile_shouldReturn0() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);