From 135fecbee3f75adbef8176f1d541e250e87dfdfe Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 15 Sep 2017 13:22:04 -0700 Subject: [PATCH] Use "mid" stable id for condition cards conditionally. When there is no suggestion, use "mid" stableId instead of "top" stableId for the header card. This avoid an animation jank: when user swipes away a suggestion, the condition summary header moves up instead of disappears then reappears. Old behavior: --- Suggestion --- --swipe--> /// Top Header /// /// Mid Header /// New behavior: --- Suggestion --- -- swipe --> /// Mid Header /// /// Mid Header /// (Notice the header id change) Change-Id: I63512d3d21382488e43dddb8819fabe4af40d101 Fixes: 65729560 Test: robotests --- .../settings/dashboard/DashboardData.java | 19 +++++--- .../settings/dashboard/DashboardDataTest.java | 48 +++++++++++++++---- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/dashboard/DashboardData.java b/src/com/android/settings/dashboard/DashboardData.java index 0fac0a2248d..b60fef368b2 100644 --- a/src/com/android/settings/dashboard/DashboardData.java +++ b/src/com/android/settings/dashboard/DashboardData.java @@ -222,15 +222,22 @@ public class DashboardData { final int hiddenSuggestion = hasSuggestions ? sizeOf(mSuggestions) - sizeOf(suggestions) : 0; + final boolean hasSuggestionAndCollapsed = hasSuggestions + && mSuggestionConditionMode == HEADER_MODE_COLLAPSED; + final boolean onlyHasConditionAndCollapsed = !hasSuggestions + && hasConditions + && mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED; + /* Top suggestion/condition header. This will be present when there is any suggestion - * and the mode is collapsed, or it only has conditions and the mode is not fully - * expanded. */ + * and the mode is collapsed */ addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion), R.layout.suggestion_condition_header, - STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER, - hasSuggestions && mSuggestionConditionMode == HEADER_MODE_COLLAPSED - || !hasSuggestions && hasConditions - && mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED); + STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER, hasSuggestionAndCollapsed); + + /* Use mid header if there is only condition & it's in collapsed mode */ + addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion), + R.layout.suggestion_condition_header, + STABLE_ID_SUGGESTION_CONDITION_MIDDLE_HEADER, onlyHasConditionAndCollapsed); /* Suggestion container. This is the card view that contains the list of suggestions. * This will be added whenever the suggestion list is not empty */ diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java index 77213f54cfe..ad257ee9044 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java @@ -16,6 +16,13 @@ package com.android.settings.dashboard; +import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_CONTAINER; +import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONDITION_FOOTER; +import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONTAINER; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.support.annotation.NonNull; import android.support.v7.util.DiffUtil; import android.support.v7.util.ListUpdateCallback; @@ -39,15 +46,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_CONTAINER; -import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONDITION_FOOTER; -import static com.android.settings.dashboard.DashboardData - .STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER; -import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONTAINER; -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - @RunWith(RobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class DashboardDataTest { @@ -214,6 +212,38 @@ public class DashboardDataTest { mDashboardDataWithTwoConditions, testResultData); } + @Test + public void testDiffUtil_RemoveOneSuggestion_causeItemRemoveAndChange() { + //Build testResultData + final List testResultData = new ArrayList<>(); + testResultData.add(new ListUpdateResult.ResultData( + ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 1)); + testResultData.add(new ListUpdateResult.ResultData( + ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 1, 1)); + // Build DashboardData + final List oneItemConditions = new ArrayList<>(); + when(mTestCondition.shouldShow()).thenReturn(true); + oneItemConditions.add(mTestCondition); + final List suggestions = new ArrayList<>(); + mTestSuggestion.title = TEST_SUGGESTION_TITLE; + suggestions.add(mTestSuggestion); + + final DashboardData oldData = new DashboardData.Builder() + .setConditions(oneItemConditions) + .setCategory(mDashboardCategory) + .setSuggestions(suggestions) + .setSuggestionConditionMode(DashboardData.HEADER_MODE_DEFAULT) + .build(); + final DashboardData newData = new DashboardData.Builder() + .setConditions(oneItemConditions) + .setSuggestions(null) + .setCategory(mDashboardCategory) + .setSuggestionConditionMode(DashboardData.HEADER_MODE_DEFAULT) + .build(); + + testDiffUtil(oldData, newData, testResultData); + } + @Test public void testDiffUtil_DeleteAllData_ResultDataOneDeleted() { //Build testResultData