Add support for delete animation in LayoutAnimation on Android

Summary:
Android follow up to #6779

**Test plan**
Tested add/removing views in the UIExample explorer with and without setting a LayoutAnimation. Tested that user interation during the animation is properly disabled.

![layout-anim-2](https://cloud.githubusercontent.com/assets/2677334/14760549/d60ebe2a-0914-11e6-8f17-ea04d8bf813b.gif)
Closes https://github.com/facebook/react-native/pull/7171

Differential Revision: D3352450

Pulled By: astreet

fbshipit-source-id: 233efa041626eb26d99511d12a924e54a10f96cc
This commit is contained in:
Janic Duplessis
2016-05-26 05:28:26 -07:00
committed by Facebook Github Bot 9
parent 4879f88a75
commit 0fb5ccf6af
7 changed files with 138 additions and 10 deletions
@@ -35,6 +35,7 @@ import com.facebook.react.bridge.SoftAssertions;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.touch.JSResponderHandler;
import com.facebook.react.uimanager.layoutanimation.LayoutAnimationController;
import com.facebook.react.uimanager.layoutanimation.LayoutAnimationListener;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
@@ -294,8 +295,8 @@ public class NativeViewHierarchyManager {
@Nullable int[] indicesToRemove,
@Nullable ViewAtIndex[] viewsToAdd,
@Nullable int[] tagsToDelete) {
ViewGroup viewToManage = (ViewGroup) mTagsToViews.get(tag);
ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(tag);
final ViewGroup viewToManage = (ViewGroup) mTagsToViews.get(tag);
final ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(tag);
if (viewToManage == null) {
throw new IllegalViewOperationException("Trying to manageChildren view with tag " + tag +
" which doesn't exist\n detail: " +
@@ -344,7 +345,17 @@ public class NativeViewHierarchyManager {
viewsToAdd,
tagsToDelete));
}
viewManager.removeViewAt(viewToManage, indicesToRemove[i]);
View viewToRemove = viewToManage.getChildAt(indexToRemove);
if (mLayoutAnimator.shouldAnimateLayout(viewToRemove) &&
arrayContains(tagsToDelete, viewToRemove.getId())) {
// The view will be removed and dropped by the 'delete' layout animation
// instead, so do nothing
} else {
viewManager.removeViewAt(viewToManage, indexToRemove);
}
lastIndexToRemove = indexToRemove;
}
}
@@ -371,7 +382,7 @@ public class NativeViewHierarchyManager {
if (tagsToDelete != null) {
for (int i = 0; i < tagsToDelete.length; i++) {
int tagToDelete = tagsToDelete[i];
View viewToDestroy = mTagsToViews.get(tagToDelete);
final View viewToDestroy = mTagsToViews.get(tagToDelete);
if (viewToDestroy == null) {
throw new IllegalViewOperationException(
"Trying to destroy unknown view tag: "
@@ -383,11 +394,31 @@ public class NativeViewHierarchyManager {
viewsToAdd,
tagsToDelete));
}
dropView(viewToDestroy);
if (mLayoutAnimator.shouldAnimateLayout(viewToDestroy)) {
mLayoutAnimator.deleteView(viewToDestroy, new LayoutAnimationListener() {
@Override
public void onAnimationEnd() {
viewManager.removeView(viewToManage, viewToDestroy);
dropView(viewToDestroy);
}
});
} else {
dropView(viewToDestroy);
}
}
}
}
private boolean arrayContains(int[] array, int ele) {
for (int curEle : array) {
if (curEle == ele) {
return true;
}
}
return false;
}
/**
* Simplified version of constructManageChildrenErrorMessage that only deals with adding children
* views