@@ -6,7 +6,8 @@ import ReactNative, {
6
6
Keyboard ,
7
7
Platform ,
8
8
UIManager ,
9
- TextInput
9
+ TextInput ,
10
+ findNodeHandle
10
11
} from 'react-native'
11
12
import { isIphoneX } from 'react-native-iphone-x-helper'
12
13
@@ -36,6 +37,32 @@ export type KeyboardAwareHOCState = {
36
37
keyboardSpace : number
37
38
}
38
39
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
+
39
66
function listenToKeyboardEvents ( ScrollableComponent : React$Component ) {
40
67
return class extends React . Component <
41
68
KeyboardAwareHOCProps ,
@@ -44,7 +71,7 @@ function listenToKeyboardEvents(ScrollableComponent: React$Component) {
44
71
_rnkasv_keyboardView : any
45
72
keyboardWillShowEvent : ?Function
46
73
keyboardWillHideEvent : ?Function
47
- position : { x : number , y : number }
74
+ position : ContentOffset
48
75
defaultResetScrollToCoords : ?{ x : number , y : number }
49
76
resetCoords: ?{ x : number , y : number }
50
77
mountedComponent: boolean
@@ -180,6 +207,48 @@ function listenToKeyboardEvents(ScrollableComponent: React$Component) {
180
207
} , keyboardOpeningTime )
181
208
}
182
209
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
+
183
252
// Keyboard actions
184
253
_updateKeyboardSpace = ( frames : Object ) => {
185
254
// Automatically scroll to focused TextInput
0 commit comments