Skip to content

Commit

Permalink
ScrollViewStickyHeader: update position (translateY) in Fabric Shadow…
Browse files Browse the repository at this point in the history
…Tree when scrolling stops

Summary:
In Fabric, some uses of the ScrollViewStickyHeader don't work after scrolling because even though the UI correctly reflects the translateY that the StickyHeader should be at, the underlying C++ Fabric ShadowTree doesn't have the updated parameters.

1. We add a mechanism to pass static props through to animated nodes; these get passed to the platform through the normal commit-diff process. This is to allow passing props to the platform that are also controlled by the animation. This mechanism could be reused elsewhere.
2. In ScrollViewStickyHeader, listen to updates for the translateY value and pass them to the platform when it stops changing - for Fabric only. This noops for non-Fabric since it's not necessary.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D21948830

fbshipit-source-id: b203ecde466732203dd12a86e2339e81f66b27e7
  • Loading branch information
JoshuaGross authored and facebook-github-bot committed Jun 9, 2020
1 parent 646605b commit fa5d3fb
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 70 deletions.
26 changes: 24 additions & 2 deletions Libraries/Animated/src/createAnimatedComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

'use strict';

const View = require('../../Components/View/View');
const {AnimatedEvent} = require('./AnimatedEvent');
const AnimatedProps = require('./nodes/AnimatedProps');
const React = require('react');
Expand All @@ -20,7 +21,18 @@ const setAndForwardRef = require('../../Utilities/setAndForwardRef');
export type AnimatedComponentType<
Props: {+[string]: mixed, ...},
Instance,
> = React.AbstractComponent<$ObjMap<Props, () => any>, Instance>;
> = React.AbstractComponent<
$ObjMap<
Props &
$ReadOnly<{
passthroughAnimatedPropExplicitValues?: React.ElementConfig<
typeof View,
>,
}>,
() => any,
>,
Instance,
>;

function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
Component: React.AbstractComponent<Props, Instance>,
Expand Down Expand Up @@ -65,6 +77,7 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
// However, setNativeProps can only be implemented on leaf native
// components. If you want to animate a composite component, you need to
// re-render it. In this case, we have a fallback that uses forceUpdate.
// This fallback is also called in Fabric.
_animatedPropsCallback = () => {
if (this._component == null) {
// AnimatedProps is created in will-mount because it's used in render.
Expand Down Expand Up @@ -119,6 +132,10 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
_attachProps(nextProps) {
const oldPropsAnimated = this._propsAnimated;

if (nextProps === oldPropsAnimated) {
return;
}

this._propsAnimated = new AnimatedProps(
nextProps,
this._animatedPropsCallback,
Expand Down Expand Up @@ -160,10 +177,15 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
});

render() {
const props = this._propsAnimated.__getValue();
const {style = {}, ...props} = this._propsAnimated.__getValue() || {};
const {style: passthruStyle = {}, ...passthruProps} =
this.props.passthroughAnimatedPropExplicitValues || {};
const mergedStyle = {...style, ...passthruStyle};
return (
<Component
{...props}
{...passthruProps}
style={mergedStyle}
ref={this._setComponentRef}
// The native driver updates views directly through the UI thread so we
// have to make sure the view doesn't get optimized away because it cannot
Expand Down
1 change: 1 addition & 0 deletions Libraries/Components/ScrollView/ScrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,7 @@ class ScrollView extends React.Component<Props, State> {
return (
<StickyHeaderComponent
key={key}
nativeID={'StickyHeader-' + key}
ref={ref => this._setStickyHeaderRef(key, ref)}
nextHeaderLayoutY={this._headerLayoutYs.get(
this._getKeyForIndex(nextIndex, childArray),
Expand Down
Loading

0 comments on commit fa5d3fb

Please sign in to comment.