Support the `Slow Animations` option of the iOS simulator (#21157)

Summary:
RN animations currently ignore the `Slow Animations` option on the iOS simulator because we don't use UIKit animations directly. This uses a private api to get the slow coefficient and use it in the native animated driver. We only compile the private api code on simulator so this won't cause issues for app store approval. One possible issue is that the api changes in new iOS versions but I think it's reasonable to do this.

Note that this won't work with JS driven animations, we could expose the slow coefficient as a constant and use that in JS but I decided not to implement it.
Pull Request resolved: https://github.com/facebook/react-native/pull/21157

Differential Revision: D9980306

Pulled By: sahrens

fbshipit-source-id: bdbce2e469261a75cb4b9a251e8e8f212bb9c4e7
This commit is contained in:
Janic Duplessis 2018-09-20 16:05:05 -07:00 коммит произвёл Facebook Github Bot
Родитель a6f47d46ca
Коммит 40bcc38d91
5 изменённых файлов: 36 добавлений и 14 удалений

Просмотреть файл

@ -10,6 +10,7 @@
#import <UIKit/UIKit.h>
#import <React/RCTConvert.h>
#import "RCTAnimationUtils.h"
#import "RCTValueAnimatedNode.h"
@interface RCTDecayAnimation ()
@ -100,7 +101,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
CGFloat value = _fromValue +
(_velocity / (1 - _deceleration)) *
(1 - exp(-(1 - _deceleration) * (currentTime - _frameStartTime) * 1000.0));
(1 - exp(-(1 - _deceleration) * (currentTime - _frameStartTime) * 1000.0 / RCTAnimationDragCoefficient()));
[self updateValue:value];

Просмотреть файл

@ -97,7 +97,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
}
_animationCurrentTime = currentTime;
NSTimeInterval currentDuration = _animationCurrentTime - _animationStartTime;
NSTimeInterval currentDuration = (_animationCurrentTime - _animationStartTime) / RCTAnimationDragCoefficient();
// Determine how many frames have passed since last update.
// Get index of frames that surround the current interval

Просмотреть файл

@ -12,6 +12,7 @@
#import <React/RCTConvert.h>
#import <React/RCTDefines.h>
#import "RCTAnimationUtils.h"
#import "RCTValueAnimatedNode.h"
@interface RCTSpringAnimation ()
@ -120,7 +121,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
} else {
// Handle frame drops, and only advance dt by a max of MAX_DELTA_TIME
deltaTime = MIN(MAX_DELTA_TIME, currentTime - _animationCurrentTime);
_t = _t + deltaTime;
_t = _t + deltaTime / RCTAnimationDragCoefficient();
}
// store the timestamp

Просмотреть файл

@ -30,3 +30,9 @@ RCT_EXTERN CGFloat RCTInterpolateValue(CGFloat value,
RCT_EXTERN CGFloat RCTRadiansToDegrees(CGFloat radians);
RCT_EXTERN CGFloat RCTDegreesToRadians(CGFloat degrees);
/**
* Coefficient to slow down animations, respects the ios
* simulator `Slow Animations (T)` option.
*/
RCT_EXTERN CGFloat RCTAnimationDragCoefficient(void);

Просмотреть файл

@ -93,3 +93,17 @@ CGFloat RCTDegreesToRadians(CGFloat degrees)
{
return degrees / 180.0 * M_PI;
}
#if TARGET_IPHONE_SIMULATOR
// Based on https://stackoverflow.com/a/13307674
float UIAnimationDragCoefficient(void);
#endif
CGFloat RCTAnimationDragCoefficient()
{
#if TARGET_IPHONE_SIMULATOR
return (CGFloat)UIAnimationDragCoefficient();
#else
return 1.0;
#endif
}