Refine animation to remove strange reshuffling animation
The issue happens mainly because two animations(move + change) running
on the same view interrupt with each other. When ItemAnimator runs the
move animation, it will change the translationX&Y in a time period.
When the change animation occurs in this period, it gets this translation
value and calculates a non-zero deta, then it would run an unnecessary
move animation, which causes the strange reshuffling.
In this cl, I skip the translation value only for the tile view when
there is pending animation.
I also add scroll operation for conditions view to make it scroll to
top after condition change.
Bug: 33839777
Bug: 33839780
Test: make -j40 RunSettingsRoboTests
Change-Id: I2152f93f756ae20cf754d6fca3525119cb4ceb1f
diff --git a/src/com/android/settings/dashboard/DashboardItemAnimator.java b/src/com/android/settings/dashboard/DashboardItemAnimator.java
index fcaba22..88e69e5 100644
--- a/src/com/android/settings/dashboard/DashboardItemAnimator.java
+++ b/src/com/android/settings/dashboard/DashboardItemAnimator.java
@@ -18,15 +18,22 @@
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView.ViewHolder;
+import com.android.settingslib.drawer.Tile;
public class DashboardItemAnimator extends DefaultItemAnimator {
@Override
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY,
int toX, int toY) {
- if (oldHolder == newHolder) {
- fromX += ViewCompat.getTranslationX(oldHolder.itemView);
- fromY += ViewCompat.getTranslationY(oldHolder.itemView);
+ final Object tag = oldHolder.itemView.getTag();
+ if (tag instanceof Tile && oldHolder == newHolder) {
+ // When this view has other move animation running, skip this value to avoid
+ // animations interrupt each other.
+ if (!isRunning()) {
+ fromX += ViewCompat.getTranslationX(oldHolder.itemView);
+ fromY += ViewCompat.getTranslationY(oldHolder.itemView);
+ }
+
if (fromX == toX && fromY == toY) {
dispatchMoveFinished(oldHolder);
return false;
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 136ccaf..ebc9b52 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -263,6 +263,7 @@
public void onConditionsChanged() {
Log.d(TAG, "onConditionsChanged");
mAdapter.setConditions(mConditionManager.getConditions());
+ mDashboard.scrollToPosition(0);
}
private class SuggestionLoader extends AsyncTask<Void, Void, List<Tile>> {
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java
index 6ca6f4d..90ff25c 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java
@@ -21,6 +21,7 @@
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.SupportItemAdapter.ViewHolder;
+import com.android.settingslib.drawer.Tile;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,20 +42,30 @@
final Context context = ShadowApplication.getInstance().getApplicationContext();
mDashboardItemAnimator = new DashboardItemAnimator();
mViewHolder = new ViewHolder(new TextView(context));
+ mViewHolder.itemView.setTag(new Tile());
}
@Test
- public void testAnimateChange_NoOffset_NoPendingAnimation() {
+ public void testAnimateChange_NoPositionChange_NoPendingAnimation() {
final boolean hasPendingAnimation = mDashboardItemAnimator
.animateChange(mViewHolder, mViewHolder, 0, 1, 0, 1);
assertThat(hasPendingAnimation).isFalse();
}
@Test
- public void testAnimateChange_HasOffset_HasPendingAnimation() {
+ public void testAnimateChange_HasPositionChange_HasPendingAnimation() {
final boolean hasPendingAnimation = mDashboardItemAnimator
.animateChange(mViewHolder, mViewHolder, 0, 0, 1, 1);
assertThat(hasPendingAnimation).isTrue();
}
+ @Test
+ public void testAnimateChange_HasRunningAnimationWhileNoPositionChange_NoPendingAnimation() {
+ // Set pending move animations
+ mDashboardItemAnimator.animateMove(mViewHolder, 0, 0, 1, 1);
+
+ final boolean hasPendingAnimation = mDashboardItemAnimator
+ .animateChange(mViewHolder, mViewHolder, 0, 1, 0, 1);
+ assertThat(hasPendingAnimation).isFalse();
+ }
}