Cleaning up some reordering issues:
-> Reorder solution should never change unless target cell changes -> Simplified code and improved the behaviour when items' jiggle animations switch from one direction to another. These transitions are now seamless and have no more strange delays. Change-Id: I35d70f275d622501851328584bfcb46eec91ff3b
This commit is contained in:
@@ -1902,7 +1902,6 @@ public class CellLayout extends ViewGroup {
|
|||||||
// This method starts or changes the reorder hint animations
|
// This method starts or changes the reorder hint animations
|
||||||
private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) {
|
private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) {
|
||||||
int childCount = mShortcutsAndWidgets.getChildCount();
|
int childCount = mShortcutsAndWidgets.getChildCount();
|
||||||
int timeForPriorAnimationToComplete = getMaxCompletionTime();
|
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
View child = mShortcutsAndWidgets.getChildAt(i);
|
View child = mShortcutsAndWidgets.getChildAt(i);
|
||||||
if (child == dragView) continue;
|
if (child == dragView) continue;
|
||||||
@@ -1911,7 +1910,7 @@ public class CellLayout extends ViewGroup {
|
|||||||
if (c != null) {
|
if (c != null) {
|
||||||
ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY,
|
ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY,
|
||||||
c.x, c.y, c.spanX, c.spanY);
|
c.x, c.y, c.spanX, c.spanY);
|
||||||
rha.animate(timeForPriorAnimationToComplete);
|
rha.animate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1920,11 +1919,13 @@ public class CellLayout extends ViewGroup {
|
|||||||
// in a temporary state, and hint at where the item will return to.
|
// in a temporary state, and hint at where the item will return to.
|
||||||
class ReorderHintAnimation {
|
class ReorderHintAnimation {
|
||||||
View child;
|
View child;
|
||||||
float deltaX;
|
float finalDeltaX;
|
||||||
float deltaY;
|
float finalDeltaY;
|
||||||
|
float initDeltaX;
|
||||||
|
float initDeltaY;
|
||||||
|
float finalScale;
|
||||||
|
float initScale;
|
||||||
private static final int DURATION = 300;
|
private static final int DURATION = 300;
|
||||||
private int repeatCount;
|
|
||||||
private boolean cancelOnCycleComplete = false;
|
|
||||||
ValueAnimator va;
|
ValueAnimator va;
|
||||||
|
|
||||||
public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1,
|
public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1,
|
||||||
@@ -1937,72 +1938,73 @@ public class CellLayout extends ViewGroup {
|
|||||||
final int y1 = mTmpPoint[1];
|
final int y1 = mTmpPoint[1];
|
||||||
final int dX = x1 - x0;
|
final int dX = x1 - x0;
|
||||||
final int dY = y1 - y0;
|
final int dY = y1 - y0;
|
||||||
deltaX = 0;
|
finalDeltaX = 0;
|
||||||
deltaY = 0;
|
finalDeltaY = 0;
|
||||||
if (dX == dY && dX == 0) {
|
if (dX == dY && dX == 0) {
|
||||||
} else {
|
} else {
|
||||||
if (dY == 0) {
|
if (dY == 0) {
|
||||||
deltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude;
|
finalDeltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude;
|
||||||
} else if (dX == 0) {
|
} else if (dX == 0) {
|
||||||
deltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude;
|
finalDeltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude;
|
||||||
} else {
|
} else {
|
||||||
double angle = Math.atan( (float) (dY) / dX);
|
double angle = Math.atan( (float) (dY) / dX);
|
||||||
deltaX = (int) (- Math.signum(dX) *
|
finalDeltaX = (int) (- Math.signum(dX) *
|
||||||
Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude));
|
Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude));
|
||||||
deltaY = (int) (- Math.signum(dY) *
|
finalDeltaY = (int) (- Math.signum(dY) *
|
||||||
Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude));
|
Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initDeltaX = child.getTranslationX();
|
||||||
|
initDeltaY = child.getTranslationY();
|
||||||
|
finalScale = 1.0f - 4.0f / child.getWidth();
|
||||||
|
initScale = child.getScaleX();
|
||||||
|
|
||||||
child.setPivotY(child.getMeasuredHeight() * 0.5f);
|
child.setPivotY(child.getMeasuredHeight() * 0.5f);
|
||||||
child.setPivotX(child.getMeasuredWidth() * 0.5f);
|
child.setPivotX(child.getMeasuredWidth() * 0.5f);
|
||||||
this.child = child;
|
this.child = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
void animate(int delay) {
|
void animate() {
|
||||||
if (mShakeAnimators.containsKey(child)) {
|
if (mShakeAnimators.containsKey(child)) {
|
||||||
ReorderHintAnimation oldAnimation = mShakeAnimators.get(child);
|
ReorderHintAnimation oldAnimation = mShakeAnimators.get(child);
|
||||||
oldAnimation.completeAnimation();
|
oldAnimation.cancel();
|
||||||
mShakeAnimators.remove(child);
|
mShakeAnimators.remove(child);
|
||||||
}
|
}
|
||||||
if (deltaX == 0 && deltaY == 0) {
|
if (finalDeltaX == 0 && finalDeltaY == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
va = ValueAnimator.ofFloat(0f, 1f);
|
va = ValueAnimator.ofFloat(0f, 1f);
|
||||||
va.setRepeatMode(ValueAnimator.REVERSE);
|
va.setRepeatMode(ValueAnimator.REVERSE);
|
||||||
va.setRepeatCount(ValueAnimator.INFINITE);
|
va.setRepeatCount(ValueAnimator.INFINITE);
|
||||||
va.setDuration(DURATION);
|
va.setDuration(DURATION);
|
||||||
va.setStartDelay((int) ((Math.max(REORDER_ANIMATION_DURATION, delay)
|
va.setStartDelay((int) (Math.random() * 60));
|
||||||
+ Math.random() * 60)));
|
|
||||||
va.addUpdateListener(new AnimatorUpdateListener() {
|
va.addUpdateListener(new AnimatorUpdateListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationUpdate(ValueAnimator animation) {
|
public void onAnimationUpdate(ValueAnimator animation) {
|
||||||
float r = ((Float) animation.getAnimatedValue()).floatValue();
|
float r = ((Float) animation.getAnimatedValue()).floatValue();
|
||||||
float x = r * deltaX;
|
float x = r * finalDeltaX + (1 - r) * initDeltaX;
|
||||||
float y = r * deltaY;
|
float y = r * finalDeltaY + (1 - r) * initDeltaY;
|
||||||
child.setTranslationX(x);
|
child.setTranslationX(x);
|
||||||
child.setTranslationY(y);
|
child.setTranslationY(y);
|
||||||
float sf = 4.0f / child.getWidth();
|
float s = r * finalScale + (1 - r) * initScale;
|
||||||
float s = 1.0f - r * sf;
|
|
||||||
child.setScaleX(s);
|
child.setScaleX(s);
|
||||||
child.setScaleY(s);
|
child.setScaleY(s);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
va.addListener(new AnimatorListenerAdapter() {
|
va.addListener(new AnimatorListenerAdapter() {
|
||||||
public void onAnimationRepeat(Animator animation) {
|
public void onAnimationRepeat(Animator animation) {
|
||||||
repeatCount++;
|
|
||||||
// We make sure to end only after a full period
|
// We make sure to end only after a full period
|
||||||
if (cancelOnCycleComplete && repeatCount % 2 == 0) {
|
initDeltaX = 0;
|
||||||
va.cancel();
|
initDeltaY = 0;
|
||||||
}
|
initScale = 1.0f;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mShakeAnimators.put(child, this);
|
mShakeAnimators.put(child, this);
|
||||||
va.start();
|
va.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void cancel() {
|
||||||
private void completeAnimation() {
|
va.cancel();
|
||||||
cancelOnCycleComplete = true;
|
|
||||||
}
|
}
|
||||||
private void completeAnimationImmediately() {
|
private void completeAnimationImmediately() {
|
||||||
va.cancel();
|
va.cancel();
|
||||||
@@ -2018,16 +2020,6 @@ public class CellLayout extends ViewGroup {
|
|||||||
s.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f));
|
s.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f));
|
||||||
s.start();
|
s.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns the time required to complete the current oscillating animation
|
|
||||||
private int completionTime() {
|
|
||||||
if (repeatCount % 2 == 0) {
|
|
||||||
return (int) (va.getDuration() - va.getCurrentPlayTime() + DURATION);
|
|
||||||
} else {
|
|
||||||
return (int) (va.getDuration() - va.getCurrentPlayTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void completeAndClearReorderHintAnimations() {
|
private void completeAndClearReorderHintAnimations() {
|
||||||
@@ -2037,14 +2029,6 @@ public class CellLayout extends ViewGroup {
|
|||||||
mShakeAnimators.clear();
|
mShakeAnimators.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMaxCompletionTime() {
|
|
||||||
int maxTime = 0;
|
|
||||||
for (ReorderHintAnimation a: mShakeAnimators.values()) {
|
|
||||||
maxTime = Math.max(maxTime, a.completionTime());
|
|
||||||
}
|
|
||||||
return maxTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void commitTempPlacement() {
|
private void commitTempPlacement() {
|
||||||
for (int i = 0; i < mCountX; i++) {
|
for (int i = 0; i < mCountX; i++) {
|
||||||
for (int j = 0; j < mCountY; j++) {
|
for (int j = 0; j < mCountY; j++) {
|
||||||
|
|||||||
@@ -2770,7 +2770,8 @@ public class Workspace extends SmoothPagedView
|
|||||||
ItemInfo info = (ItemInfo) d.dragInfo;
|
ItemInfo info = (ItemInfo) d.dragInfo;
|
||||||
|
|
||||||
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
|
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
|
||||||
(int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell);
|
(int) mDragViewVisualCenter[1], item.spanX, item.spanY,
|
||||||
|
mDragTargetLayout, mTargetCell);
|
||||||
|
|
||||||
setCurrentDropOverCell(mTargetCell[0], mTargetCell[1]);
|
setCurrentDropOverCell(mTargetCell[0], mTargetCell[1]);
|
||||||
|
|
||||||
@@ -2790,11 +2791,6 @@ public class Workspace extends SmoothPagedView
|
|||||||
minSpanY = item.minSpanY;
|
minSpanY = item.minSpanY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] reorderPosition = new int[2];
|
|
||||||
reorderPosition = findNearestArea((int) mDragViewVisualCenter[0],
|
|
||||||
(int) mDragViewVisualCenter[1], item.spanX, item.spanY, mDragTargetLayout,
|
|
||||||
reorderPosition);
|
|
||||||
|
|
||||||
boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
|
boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int)
|
||||||
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
|
mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX,
|
||||||
item.spanY, child, mTargetCell);
|
item.spanY, child, mTargetCell);
|
||||||
@@ -2805,8 +2801,9 @@ public class Workspace extends SmoothPagedView
|
|||||||
mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false,
|
mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false,
|
||||||
d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
|
d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
|
||||||
} else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
|
} else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
|
||||||
&& !mReorderAlarm.alarmPending() && (mLastReorderX != reorderPosition[0] ||
|
&& !mReorderAlarm.alarmPending() && (mLastReorderX != mTargetCell[0] ||
|
||||||
mLastReorderY != reorderPosition[1])) {
|
mLastReorderY != mTargetCell[1])) {
|
||||||
|
|
||||||
// Otherwise, if we aren't adding to or creating a folder and there's no pending
|
// Otherwise, if we aren't adding to or creating a folder and there's no pending
|
||||||
// reorder, then we schedule a reorder
|
// reorder, then we schedule a reorder
|
||||||
ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
|
ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
|
||||||
|
|||||||
Reference in New Issue
Block a user