@@ -6,7 +6,8 @@ import ReactNative, {
66 Keyboard ,
77 Platform ,
88 UIManager ,
9- TextInput
9+ TextInput ,
10+ findNodeHandle
1011} from 'react-native'
1112import { isIphoneX } from 'react-native-iphone-x-helper'
1213
@@ -36,6 +37,32 @@ export type KeyboardAwareHOCState = {
3637 keyboardSpace : number
3738}
3839
40+ export type ElementLayout = {
41+ x : number ,
42+ y : number ,
43+ width : number ,
44+ height : number
45+ }
46+
47+ export type ContentOffset = {
48+ x : number ,
49+ y : number
50+ }
51+
52+ export type ScrollPosition = {
53+ x : number ,
54+ y : number ,
55+ animated : boolean
56+ }
57+
58+ export type ScrollIntoViewOptions = ?{
59+ getScrollPosition ?: (
60+ parentLayout : ElementLayout ,
61+ childLayout : ElementLayout ,
62+ contentOffset : ContentOffset
63+ ) => ScrollPosition
64+ }
65+
3966function listenToKeyboardEvents ( ScrollableComponent : React$Component ) {
4067 return class extends React . Component <
4168 KeyboardAwareHOCProps ,
@@ -44,7 +71,7 @@ function listenToKeyboardEvents(ScrollableComponent: React$Component) {
4471 _rnkasv_keyboardView : any
4572 keyboardWillShowEvent : ?Function
4673 keyboardWillHideEvent : ?Function
47- position : { x : number , y : number }
74+ position : ContentOffset
4875 defaultResetScrollToCoords : ?{ x : number , y : number }
4976 resetCoords: ?{ x : number , y : number }
5077 mountedComponent: boolean
@@ -180,6 +207,48 @@ function listenToKeyboardEvents(ScrollableComponent: React$Component) {
180207 } , keyboardOpeningTime )
181208 }
182209
210+ scrollIntoView = async (
211+ element : React . Element < * > ,
212+ options : ScrollIntoViewOptions = { }
213+ ) => {
214+ if ( ! this . _rnkasv_keyboardView || ! element ) {
215+ return
216+ }
217+
218+ const [
219+ parentLayout ,
220+ childLayout
221+ ] = await Promise . all ( [
222+ this . _measureElement ( this . _rnkasv_keyboardView ) ,
223+ this . _measureElement ( element )
224+ ] )
225+
226+ const getScrollPosition = options . getScrollPosition || this . _defaultGetScrollPosition
227+ const { x, y, animated } = getScrollPosition ( parentLayout , childLayout , this . position )
228+ this . scrollToPosition ( x , y , animated )
229+ }
230+
231+ _defaultGetScrollPosition = (
232+ parentLayout : ElementLayout ,
233+ childLayout : ElementLayout ,
234+ contentOffset : ContentOffset
235+ ) : ScrollPosition => {
236+ return {
237+ x : 0 ,
238+ y : Math . max ( 0 , childLayout . y - parentLayout . y + contentOffset . y ) ,
239+ animated : true ,
240+ }
241+ }
242+
243+ _measureElement = ( element : React . Element < * > ) : Promise < ElementLayout > => {
244+ const node = findNodeHandle ( element )
245+ return new Promise ( ( resolve : ( ElementLayout ) = > void ) => {
246+ UIManager . measureInWindow ( node , ( x : number , y : number , width : number , height : number ) => {
247+ resolve ( { x, y, width, height } )
248+ } )
249+ } )
250+ }
251+
183252 // Keyboard actions
184253 _updateKeyboardSpace = ( frames : Object ) => {
185254 // Automatically scroll to focused TextInput
0 commit comments