LayoutAnimations: allow Paragraph props to be interpolated

Summary:
1. Split out the prop interpolation function out of the View ComponentDescriptor, into an inline'd function that can be used elsewhere.
2. Call it from View and from Paragraph component descriptors.

This causes animations including Text to look normal on iOS.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D21635473

fbshipit-source-id: 470f43fd24a6e80d8696ee2f2a09d9e693b7f280
This commit is contained in:
Joshua Gross 2020-05-20 14:11:18 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 3cbafcccba
Коммит a799367baf
3 изменённых файлов: 74 добавлений и 26 удалений

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

@ -9,6 +9,7 @@
#include "ParagraphShadowNode.h"
#include <react/components/view/ViewPropsInterpolation.h>
#include <react/config/ReactNativeConfig.h>
#include <react/core/ConcreteComponentDescriptor.h>
#include <react/textlayoutmanager/TextLayoutManager.h>
@ -30,6 +31,18 @@ class ParagraphComponentDescriptor final
textLayoutManager_ = std::make_shared<TextLayoutManager>(contextContainer_);
}
virtual SharedProps interpolateProps(
float animationProgress,
const SharedProps &props,
const SharedProps &newProps) const override {
SharedProps interpolatedPropsShared = cloneProps(newProps, {});
interpolateViewProps(
animationProgress, props, newProps, interpolatedPropsShared);
return interpolatedPropsShared;
};
protected:
void adopt(UnsharedShadowNode shadowNode) const override {
ConcreteComponentDescriptor::adopt(shadowNode);

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

@ -10,6 +10,7 @@
#include <react/components/view/ViewShadowNode.h>
#include <react/core/ConcreteComponentDescriptor.h>
#include "ViewProps.h"
#include "ViewPropsInterpolation.h"
namespace facebook {
namespace react {
@ -24,34 +25,10 @@ class ViewComponentDescriptor
float animationProgress,
const SharedProps &props,
const SharedProps &newProps) const override {
ViewProps const *oldViewProps =
dynamic_cast<ViewProps const *>(props.get());
ViewProps const *newViewProps =
dynamic_cast<ViewProps const *>(newProps.get());
SharedProps interpolatedPropsShared = cloneProps(newProps, {});
ViewProps *interpolatedProps = const_cast<ViewProps *>(
dynamic_cast<ViewProps const *>(interpolatedPropsShared.get()));
interpolatedProps->opacity = oldViewProps->opacity +
(newViewProps->opacity - oldViewProps->opacity) * animationProgress;
interpolatedProps->transform = Transform::Interpolate(
animationProgress, oldViewProps->transform, newViewProps->transform);
// Android uses RawProps, not props, to update props on the platform...
// Since interpolated props don't interpolate at all using RawProps, we need
// to "re-hydrate" raw props after interpolating. This is what actually gets
// sent to the mounting layer. This is a temporary hack, only for platforms
// that use RawProps/folly::dynamic instead of concrete props on the
// mounting layer. Once we can remove this, we should change `rawProps` to
// be const again.
#ifdef ANDROID
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity;
interpolatedProps->rawProps["transform"] =
(folly::dynamic)interpolatedProps->transform;
#endif
interpolateViewProps(
animationProgress, props, newProps, interpolatedPropsShared);
return interpolatedPropsShared;
};

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

@ -0,0 +1,58 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "ViewProps.h"
namespace facebook {
namespace react {
/**
* Given animation progress, old props, new props, and an "interpolated" shared
* props struct, this will mutate the "interpolated" struct in-place to give it
* values interpolated between the old and new props.
*/
static inline void interpolateViewProps(
Float animationProgress,
const SharedProps &oldPropsShared,
const SharedProps &newPropsShared,
SharedProps &interpolatedPropsShared) {
ViewProps const *oldViewProps =
dynamic_cast<ViewProps const *>(oldPropsShared.get());
ViewProps const *newViewProps =
dynamic_cast<ViewProps const *>(newPropsShared.get());
ViewProps *interpolatedProps = const_cast<ViewProps *>(
dynamic_cast<ViewProps const *>(interpolatedPropsShared.get()));
assert(
oldViewProps != nullptr && newViewProps != nullptr &&
interpolatedProps != nullptr);
interpolatedProps->opacity = oldViewProps->opacity +
(newViewProps->opacity - oldViewProps->opacity) * animationProgress;
interpolatedProps->transform = Transform::Interpolate(
animationProgress, oldViewProps->transform, newViewProps->transform);
// Android uses RawProps, not props, to update props on the platform...
// Since interpolated props don't interpolate at all using RawProps, we need
// to "re-hydrate" raw props after interpolating. This is what actually gets
// sent to the mounting layer. This is a temporary hack, only for platforms
// that use RawProps/folly::dynamic instead of concrete props on the
// mounting layer. Once we can remove this, we should change `rawProps` to
// be const again.
#ifdef ANDROID
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity;
interpolatedProps->rawProps["transform"] =
(folly::dynamic)interpolatedProps->transform;
#endif
}
} // namespace react
} // namespace facebook