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);