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
This commit is contained in:
@@ -18,15 +18,22 @@ package com.android.settings.dashboard;
|
|||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v7.widget.DefaultItemAnimator;
|
import android.support.v7.widget.DefaultItemAnimator;
|
||||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||||
|
import com.android.settingslib.drawer.Tile;
|
||||||
|
|
||||||
public class DashboardItemAnimator extends DefaultItemAnimator {
|
public class DashboardItemAnimator extends DefaultItemAnimator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY,
|
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY,
|
||||||
int toX, int toY) {
|
int toX, int toY) {
|
||||||
if (oldHolder == newHolder) {
|
final Object tag = oldHolder.itemView.getTag();
|
||||||
fromX += ViewCompat.getTranslationX(oldHolder.itemView);
|
if (tag instanceof Tile && oldHolder == newHolder) {
|
||||||
fromY += ViewCompat.getTranslationY(oldHolder.itemView);
|
// 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) {
|
if (fromX == toX && fromY == toY) {
|
||||||
dispatchMoveFinished(oldHolder);
|
dispatchMoveFinished(oldHolder);
|
||||||
return false;
|
return false;
|
||||||
|
@@ -263,6 +263,7 @@ public class DashboardSummary extends InstrumentedPreferenceFragment
|
|||||||
public void onConditionsChanged() {
|
public void onConditionsChanged() {
|
||||||
Log.d(TAG, "onConditionsChanged");
|
Log.d(TAG, "onConditionsChanged");
|
||||||
mAdapter.setConditions(mConditionManager.getConditions());
|
mAdapter.setConditions(mConditionManager.getConditions());
|
||||||
|
mDashboard.scrollToPosition(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SuggestionLoader extends AsyncTask<Void, Void, List<Tile>> {
|
private class SuggestionLoader extends AsyncTask<Void, Void, List<Tile>> {
|
||||||
|
@@ -21,6 +21,7 @@ import android.widget.TextView;
|
|||||||
import com.android.settings.SettingsRobolectricTestRunner;
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.dashboard.SupportItemAdapter.ViewHolder;
|
import com.android.settings.dashboard.SupportItemAdapter.ViewHolder;
|
||||||
|
import com.android.settingslib.drawer.Tile;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -41,20 +42,30 @@ public class DashboardItemAnimatorTest {
|
|||||||
final Context context = ShadowApplication.getInstance().getApplicationContext();
|
final Context context = ShadowApplication.getInstance().getApplicationContext();
|
||||||
mDashboardItemAnimator = new DashboardItemAnimator();
|
mDashboardItemAnimator = new DashboardItemAnimator();
|
||||||
mViewHolder = new ViewHolder(new TextView(context));
|
mViewHolder = new ViewHolder(new TextView(context));
|
||||||
|
mViewHolder.itemView.setTag(new Tile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnimateChange_NoOffset_NoPendingAnimation() {
|
public void testAnimateChange_NoPositionChange_NoPendingAnimation() {
|
||||||
final boolean hasPendingAnimation = mDashboardItemAnimator
|
final boolean hasPendingAnimation = mDashboardItemAnimator
|
||||||
.animateChange(mViewHolder, mViewHolder, 0, 1, 0, 1);
|
.animateChange(mViewHolder, mViewHolder, 0, 1, 0, 1);
|
||||||
assertThat(hasPendingAnimation).isFalse();
|
assertThat(hasPendingAnimation).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnimateChange_HasOffset_HasPendingAnimation() {
|
public void testAnimateChange_HasPositionChange_HasPendingAnimation() {
|
||||||
final boolean hasPendingAnimation = mDashboardItemAnimator
|
final boolean hasPendingAnimation = mDashboardItemAnimator
|
||||||
.animateChange(mViewHolder, mViewHolder, 0, 0, 1, 1);
|
.animateChange(mViewHolder, mViewHolder, 0, 0, 1, 1);
|
||||||
assertThat(hasPendingAnimation).isTrue();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user