iOS-specific LayoutAnimation integration

Summary:
Turn on Fabric LayoutAnimations on iOS.

I will gate this change behind a QE before landing.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D21583932

fbshipit-source-id: 0e0f988b44af37eb6fb22cccb48b0c7aa5020ca7
This commit is contained in:
Joshua Gross
2020-05-20 14:16:47 -07:00
committed by Facebook GitHub Bot
parent 076ba4c920
commit e781b31489
2 changed files with 89 additions and 2 deletions
+6
View File
@@ -64,6 +64,12 @@ NS_ASSUME_NONNULL_BEGIN
- (facebook::react::MountingCoordinator::Shared)mountingCoordinatorWithSurfaceId:(facebook::react::SurfaceId)surfaceId;
- (void)onAnimationStarted;
- (void)onAllAnimationsComplete;
- (void)animationTick;
@end
NS_ASSUME_NONNULL_END
+83 -2
View File
@@ -7,10 +7,12 @@
#import "RCTScheduler.h"
#import <react/animations/LayoutAnimationDriver.h>
#import <react/componentregistry/ComponentDescriptorFactory.h>
#import <react/debug/SystraceSection.h>
#import <react/scheduler/Scheduler.h>
#import <react/scheduler/SchedulerDelegate.h>
#include <react/utils/RunLoopObserver.h>
#import <React/RCTFollyConvert.h>
@@ -61,23 +63,82 @@ class SchedulerDelegateProxy : public SchedulerDelegate {
void *scheduler_;
};
class LayoutAnimationDelegateProxy : public LayoutAnimationStatusDelegate, public RunLoopObserver::Delegate {
public:
LayoutAnimationDelegateProxy(void *scheduler) : scheduler_(scheduler) {}
virtual ~LayoutAnimationDelegateProxy() {}
void onAnimationStarted() override
{
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler onAnimationStarted];
}
/**
* Called when the LayoutAnimation engine completes all pending animations.
*/
void onAllAnimationsComplete() override
{
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler onAllAnimationsComplete];
}
void activityDidChange(RunLoopObserver::Delegate const *delegate, RunLoopObserver::Activity activity) const
noexcept override
{
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler animationTick];
}
private:
void *scheduler_;
};
@implementation RCTScheduler {
std::shared_ptr<Scheduler> _scheduler;
std::shared_ptr<LayoutAnimationDriver> _animationDriver;
std::shared_ptr<SchedulerDelegateProxy> _delegateProxy;
std::shared_ptr<LayoutAnimationDelegateProxy> _layoutAnimationDelegateProxy;
RunLoopObserver::Unique _uiRunLoopObserver;
BOOL _layoutAnimationsEnabled;
}
- (instancetype)initWithToolbox:(facebook::react::SchedulerToolbox)toolbox
{
if (self = [super init]) {
auto reactNativeConfig =
toolbox.contextContainer->at<std::shared_ptr<const ReactNativeConfig>>("ReactNativeConfig");
_layoutAnimationsEnabled = reactNativeConfig->getBool("react_fabric:enabled_layout_animations_ios");
_delegateProxy = std::make_shared<SchedulerDelegateProxy>((__bridge void *)self);
_scheduler = std::make_shared<Scheduler>(toolbox, nullptr, _delegateProxy.get());
if (_layoutAnimationsEnabled) {
_layoutAnimationDelegateProxy = std::make_shared<LayoutAnimationDelegateProxy>((__bridge void *)self);
_animationDriver = std::make_unique<LayoutAnimationDriver>(_layoutAnimationDelegateProxy.get());
_uiRunLoopObserver =
toolbox.mainRunLoopObserverFactory(RunLoopObserver::Activity::BeforeWaiting, _layoutAnimationDelegateProxy);
_uiRunLoopObserver->setDelegate(_layoutAnimationDelegateProxy.get());
}
_scheduler = std::make_shared<Scheduler>(
toolbox, (_animationDriver ? _animationDriver.get() : nullptr), _delegateProxy.get());
}
return self;
}
- (void)animationTick
{
_scheduler->animationTick();
}
- (void)dealloc
{
if (_animationDriver) {
_animationDriver->setLayoutAnimationStatusDelegate(nullptr);
}
_animationDriver = nullptr;
_scheduler->setDelegate(nullptr);
}
@@ -90,7 +151,13 @@ class SchedulerDelegateProxy : public SchedulerDelegate {
SystraceSection s("-[RCTScheduler startSurfaceWithSurfaceId:...]");
auto props = convertIdToFollyDynamic(initialProps);
_scheduler->startSurface(surfaceId, RCTStringFromNSString(moduleName), props, layoutConstraints, layoutContext);
_scheduler->startSurface(
surfaceId,
RCTStringFromNSString(moduleName),
props,
layoutConstraints,
layoutContext,
(_animationDriver ? _animationDriver.get() : nullptr));
_scheduler->renderTemplateToSurface(
surfaceId, props.getDefault("navigationConfig").getDefault("initialUITemplate", "").getString());
}
@@ -127,4 +194,18 @@ class SchedulerDelegateProxy : public SchedulerDelegate {
return _scheduler->findMountingCoordinator(surfaceId);
}
- (void)onAnimationStarted
{
if (_uiRunLoopObserver) {
_uiRunLoopObserver->enable();
}
}
- (void)onAllAnimationsComplete
{
if (_uiRunLoopObserver) {
_uiRunLoopObserver->disable();
}
}
@end