Revert D4494386: [react-native][PR] BREAKING - Remove LayoutAnimation experimental flag on Android

Differential Revision: D4494386

fbshipit-source-id: 1ba6fc60467d1c3347c90e52a3251e6591a99e25
This commit is contained in:
Fred Liu 2017-03-09 20:13:12 -08:00 committed by Facebook Github Bot
parent b47000a051
commit 28ed5eddf2
8 changed files with 86 additions and 3 deletions

View File

@ -58,6 +58,11 @@ var NUM_SECTIONS = 100;
var NUM_ROWS_PER_SECTION = 10; var NUM_ROWS_PER_SECTION = 10;
class Thumb extends React.Component { class Thumb extends React.Component {
componentWillMount() {
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
}
_getThumbIdx = () => { _getThumbIdx = () => {
return Math.floor(Math.random() * THUMB_URLS.length); return Math.floor(Math.random() * THUMB_URLS.length);
}; };

View File

@ -46,6 +46,8 @@ const nativeImageSource = require('nativeImageSource');
import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer'; import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer';
UIManager.setLayoutAnimationEnabledExperimental(true);
const DRAWER_WIDTH_LEFT = 56; const DRAWER_WIDTH_LEFT = 56;
type Props = { type Props = {

View File

@ -88,6 +88,10 @@ function create(duration: number, type, creationProp): Config {
update: { update: {
type, type,
}, },
delete: {
type,
property: creationProp,
},
}; };
} }
@ -108,6 +112,10 @@ var Presets = {
type: Types.spring, type: Types.spring,
springDamping: 0.4, springDamping: 0.4,
}, },
delete: {
type: Types.linear,
property: Properties.opacity,
},
}, },
}; };
@ -116,6 +124,10 @@ var Presets = {
* next layout happens. * next layout happens.
* *
* A common way to use this API is to call it before calling `setState`. * A common way to use this API is to call it before calling `setState`.
*
* Note that in order to get this to work on **Android** you need to set the following flags via `UIManager`:
*
* UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
*/ */
var LayoutAnimation = { var LayoutAnimation = {
/** /**

View File

@ -76,6 +76,8 @@ public class NativeViewHierarchyManager {
private final RootViewManager mRootViewManager; private final RootViewManager mRootViewManager;
private final LayoutAnimationController mLayoutAnimator = new LayoutAnimationController(); private final LayoutAnimationController mLayoutAnimator = new LayoutAnimationController();
private boolean mLayoutAnimationEnabled;
public NativeViewHierarchyManager(ViewManagerRegistry viewManagers) { public NativeViewHierarchyManager(ViewManagerRegistry viewManagers) {
this(viewManagers, new RootViewManager()); this(viewManagers, new RootViewManager());
} }
@ -110,6 +112,10 @@ public class NativeViewHierarchyManager {
return mAnimationRegistry; return mAnimationRegistry;
} }
public void setLayoutAnimationEnabled(boolean enabled) {
mLayoutAnimationEnabled = enabled;
}
public void updateProperties(int tag, ReactStylesDiffMap props) { public void updateProperties(int tag, ReactStylesDiffMap props) {
UiThreadUtil.assertOnUiThread(); UiThreadUtil.assertOnUiThread();
@ -186,7 +192,8 @@ public class NativeViewHierarchyManager {
} }
private void updateLayout(View viewToUpdate, int x, int y, int width, int height) { private void updateLayout(View viewToUpdate, int x, int y, int width, int height) {
if (mLayoutAnimator.shouldAnimateLayout(viewToUpdate)) { if (mLayoutAnimationEnabled &&
mLayoutAnimator.shouldAnimateLayout(viewToUpdate)) {
mLayoutAnimator.applyLayoutUpdate(viewToUpdate, x, y, width, height); mLayoutAnimator.applyLayoutUpdate(viewToUpdate, x, y, width, height);
} else { } else {
viewToUpdate.layout(x, y, x + width, y + height); viewToUpdate.layout(x, y, x + width, y + height);
@ -356,7 +363,8 @@ public class NativeViewHierarchyManager {
View viewToRemove = viewManager.getChildAt(viewToManage, indexToRemove); View viewToRemove = viewManager.getChildAt(viewToManage, indexToRemove);
if (mLayoutAnimator.shouldAnimateLayout(viewToRemove) && if (mLayoutAnimationEnabled &&
mLayoutAnimator.shouldAnimateLayout(viewToRemove) &&
arrayContains(tagsToDelete, viewToRemove.getId())) { arrayContains(tagsToDelete, viewToRemove.getId())) {
// The view will be removed and dropped by the 'delete' layout animation // The view will be removed and dropped by the 'delete' layout animation
// instead, so do nothing // instead, so do nothing
@ -403,7 +411,8 @@ public class NativeViewHierarchyManager {
tagsToDelete)); tagsToDelete));
} }
if (mLayoutAnimator.shouldAnimateLayout(viewToDestroy)) { if (mLayoutAnimationEnabled &&
mLayoutAnimator.shouldAnimateLayout(viewToDestroy)) {
mLayoutAnimator.deleteView(viewToDestroy, new LayoutAnimationListener() { mLayoutAnimator.deleteView(viewToDestroy, new LayoutAnimationListener() {
@Override @Override
public void onAnimationEnd() { public void onAnimationEnd() {

View File

@ -569,6 +569,21 @@ public class UIImplementation {
mOperationsQueue.enqueueRemoveAnimation(animationID); mOperationsQueue.enqueueRemoveAnimation(animationID);
} }
/**
* LayoutAnimation API on Android is currently experimental. Therefore, it needs to be enabled
* explicitly in order to avoid regression in existing application written for iOS using this API.
*
* Warning : This method will be removed in future version of React Native, and layout animation
* will be enabled by default, so always check for its existence before invoking it.
*
* TODO(9139831) : remove this method once layout animation is fully stable.
*
* @param enabled whether layout animation is enabled or not
*/
public void setLayoutAnimationEnabledExperimental(boolean enabled) {
mOperationsQueue.enqueueSetLayoutAnimationEnabled(enabled);
}
/** /**
* Configure an animation to be used for the native layout changes, and native views * Configure an animation to be used for the native layout changes, and native views
* creation. The animation will only apply during the current batch operations. * creation. The animation will only apply during the current batch operations.

View File

@ -474,6 +474,22 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
mUIImplementation.showPopupMenu(reactTag, items, error, success); mUIImplementation.showPopupMenu(reactTag, items, error, success);
} }
/**
* LayoutAnimation API on Android is currently experimental. Therefore, it needs to be enabled
* explicitly in order to avoid regression in existing application written for iOS using this API.
*
* Warning : This method will be removed in future version of React Native, and layout animation
* will be enabled by default, so always check for its existence before invoking it.
*
* TODO(9139831) : remove this method once layout animation is fully stable.
*
* @param enabled whether layout animation is enabled or not
*/
@ReactMethod
public void setLayoutAnimationEnabledExperimental(boolean enabled) {
mUIImplementation.setLayoutAnimationEnabledExperimental(enabled);
}
/** /**
* Configure an animation to be used for the native layout changes, and native views * Configure an animation to be used for the native layout changes, and native views
* creation. The animation will only apply during the current batch operations. * creation. The animation will only apply during the current batch operations.

View File

@ -351,6 +351,19 @@ public class UIViewOperationQueue {
} }
} }
private class SetLayoutAnimationEnabledOperation implements UIOperation {
private final boolean mEnabled;
private SetLayoutAnimationEnabledOperation(final boolean enabled) {
mEnabled = enabled;
}
@Override
public void execute() {
mNativeViewHierarchyManager.setLayoutAnimationEnabled(mEnabled);
}
}
private class ConfigureLayoutAnimationOperation implements UIOperation { private class ConfigureLayoutAnimationOperation implements UIOperation {
private final ReadableMap mConfig; private final ReadableMap mConfig;
@ -686,6 +699,11 @@ public class UIViewOperationQueue {
mOperations.add(new RemoveAnimationOperation(animationID)); mOperations.add(new RemoveAnimationOperation(animationID));
} }
public void enqueueSetLayoutAnimationEnabled(
final boolean enabled) {
mOperations.add(new SetLayoutAnimationEnabledOperation(enabled));
}
public void enqueueConfigureLayoutAnimation( public void enqueueConfigureLayoutAnimation(
final ReadableMap config, final ReadableMap config,
final Callback onSuccess, final Callback onSuccess,

View File

@ -387,6 +387,12 @@ it provides much less control than `Animated` and other animation libraries, so
you may need to use another approach if you can't get `LayoutAnimation` to do you may need to use another approach if you can't get `LayoutAnimation` to do
what you want. what you want.
Note that in order to get this to work on **Android** you need to set the following flags via `UIManager`:
```javascript
UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
```
![](img/LayoutAnimationExample.gif) ![](img/LayoutAnimationExample.gif)
```javascript ```javascript