From db74e713fe68b8509777baf34db8a7bb496091e0 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Wed, 3 Feb 2016 11:12:58 -0800 Subject: [PATCH] Fix scrollTo when using RefreshControl on Android Summary: The issue is that the ScrollResponder mixin assumes that the native scrollable node is the top level element and gets it using `React.findNodeHandle(this)` but since Android wraps the native `ScrollView` component with the `RefreshControl`, it finds the native `RefreshControl` node instead and the scroll command gets ignored because it doesn't exists. This adds a hook to ScrollResponder mixin to allow specifying what is the native scrollable node. The bug can be reproduced using this https://gist.github.com/janicduplessis/871c0b6d3ad0acaacba9 in UIExplorer. Fixes #5725 Closes https://github.com/facebook/react-native/pull/5736 Reviewed By: svcscm Differential Revision: D2896125 Pulled By: nicklockwood fb-gh-sync-id: 0a00a20551421982c5bc519c542774877ba15c9b --- Libraries/Components/ScrollResponder.js | 15 +++++++++++++-- Libraries/Components/ScrollView/ScrollView.js | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index 65531aa2fe..52c6c946b8 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -347,6 +347,17 @@ var ScrollResponderMixin = { return isAnimating; }, + /** + * Returns the node that represents native view that can be scrolled. + * Components can pass what node to use by defining a `getScrollableNode` + * function otherwise `this` is used. + */ + scrollResponderGetScrollableNode: function(): any { + return this.getScrollableNode ? + this.getScrollableNode() : + React.findNodeHandle(this); + }, + /** * A helper function to scroll to a specific point in the scrollview. * This is currently used to help focus on child textviews, but can also @@ -369,7 +380,7 @@ var ScrollResponderMixin = { ({x, y, animated} = x || {}); } UIManager.dispatchViewManagerCommand( - React.findNodeHandle(this), + this.scrollResponderGetScrollableNode(), UIManager.RCTScrollView.Commands.scrollTo, [x || 0, y || 0, animated !== false], ); @@ -401,7 +412,7 @@ var ScrollResponderMixin = { } else if (typeof animated !== 'undefined') { console.warn('`scrollResponderZoomTo` `animated` argument is deprecated. Use `options.animated` instead'); } - ScrollViewManager.zoomToRect(React.findNodeHandle(this), rect, animated !== false); + ScrollViewManager.zoomToRect(this.scrollResponderGetScrollableNode(), rect, animated !== false); } }, diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 279712808b..d9d7102460 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -355,6 +355,10 @@ var ScrollView = React.createClass({ return this; }, + getScrollableNode: function(): any { + return React.findNodeHandle(this.refs[SCROLLVIEW]); + }, + getInnerViewNode: function(): any { return React.findNodeHandle(this.refs[INNERVIEW]); },