Skip to content

Instantly share code, notes, and snippets.

@bhrott
Created August 22, 2019 10:41
Show Gist options
  • Save bhrott/40cb6b20be9f533242aa7c8cf98e0484 to your computer and use it in GitHub Desktop.
Save bhrott/40cb6b20be9f533242aa7c8cf98e0484 to your computer and use it in GitHub Desktop.
React-Native: Scrollview + Keyboard handling
import React, { useEffect, useState } from 'react'
import { Keyboard, TextInput, UIManager, Platform } from 'react-native'
const AndroidKeyboardView = () => {
return null
}
const IOSKeyboardView = props => {
const [keyboardInfo, setKeyboardInfo] = useState(0)
const [keyboardDidShowEvent, setKeyboardDidShowEvent] = useState(null)
const [keyboardDidHideEvent, setKeyboardDidHideEvent] = useState(null)
const [lastFocusedInputInfo, setLastFocusedInputInfo] = useState(null)
useEffect(() => {
setKeyboardDidShowEvent(
Keyboard.addListener('keyboardDidShow', e => {
setKeyboardInfo(e)
})
)
setKeyboardDidHideEvent(
Keyboard.addListener('keyboardDidHide', () => {
setKeyboardInfo(null)
})
)
}, [])
useEffect(() => {
return () => {
if (!keyboardDidShowEvent) {
return
}
keyboardDidShowEvent.remove()
keyboardDidHideEvent.remove()
}
}, [keyboardDidShowEvent, keyboardDidHideEvent])
useEffect(() => {
const { State: TextInputState } = TextInput
const currentlyFocusedField = TextInputState.currentlyFocusedField()
const scrollView = props.scrollView.current
if (currentlyFocusedField && keyboardInfo) {
UIManager.measure(
currentlyFocusedField,
(originX, originY, width, height, pageX, pageY) => {
setLastFocusedInputInfo({
originX,
originY,
width,
height,
pageX,
pageY,
})
const keyboardY = keyboardInfo.endCoordinates.screenY
const inputY = pageY + height
const distance = inputY - keyboardY
if (distance > 0) {
const scrollPositionTarget = keyboardY - distance
scrollView.setNativeProps({
contentInset: { bottom: 200, top: 0, left: 0, right: 0 },
})
scrollView.scrollTo({ y: scrollPositionTarget })
}
}
)
} else {
scrollView.setNativeProps({
contentInset: { bottom: 0, top: 0, left: 0, right: 0 },
})
if (lastFocusedInputInfo) {
scrollView.scrollTo({ y: lastFocusedInputInfo.originY })
}
}
}, [keyboardInfo])
return null
}
export const KeyboardView = props => {
if (Platform.OS === 'ios') {
return <IOSKeyboardView {...props} />
}
return <AndroidKeyboardView {...props} />
}

Usage

const scrollViewRef = useRef(null)

<ScrollView
    keyboardShouldPersistTaps='always'
    keyboardDismissMode='on-drag'
    ref={scrollViewRef}
  >
  <View>
    ......
    <KeyboardView scrollView={scrollViewRef} />
  </View>
</ScrollView>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment