When multiline prop is set in the TextInput it doesn't scroll properly
Can you set up a repro case in order to be able to solve it? Thanks!
Just ran into this with KeyboardAwareScrollView too.
Reproduction case:
<KeyboardAwareFlatList
data={optionsList}
renderItem={this._renderItem.bind(this)}
keyExtractor={this._keyExtractor}
showsVerticalScrollIndicator={false}
/>
And in _renderItem function there is an item that renders a text field (TextInput) as following:
<TextInput
{...this.props}
multiline={true} />
When the multiline prop is set to _false_ it works fine and scrolls up to text field as intended, but when it is set to _true_ , it fails to scroll up/center the text field as in last case.
Solution/Workaround: I added
extraHeight
prop like this extraHeight={texInputHeight} for now.
Ugh, yes, this has been an ongoing issue since first versions. I will try to get a solution as soon as I can.
I can confirm this is an issue. The workaround is nice, thanks @omar-salah-elboredy . Sadly, it adds an empty block which has a height of extraHeight below the scrollView, which can not be reached :/
I have same issue with @WaldoJeffers . Please help.
One solution is #250. componentDidUpdate() fires an .update() event and this repositions the TextInput directly above the keyboard.
update = () => {
const currentlyFocusedField = TextInput.State.currentlyFocusedField()
const responder = this.getScrollResponder()
if (!currentlyFocusedField || !responder) {
return
}
this._scrollToFocusedInputWithNodeHandle(
currentlyFocusedField
)
}
Update: There's now a PR waiting for review that fixes this issue among others (ideally any time the TextInput goes behind the keyboard. Please check out #251
On RN 0.56 #251 didn't work
[KeyboardAwareFlatList]
At the bottom, the TextInput gets the focus and it can be achieved at the top. But when the keyboard shrinks, it doesn't restore its original position

What is the status on this issue?
@bugs181 Any updates Levi ? 馃槃
Just encountered this issue on RN 0.56. For anyone finding this I was able to workaround this by hacking it together like so:
render() {
<KeyboardAwareScrollView
innerRef={ref => {
this.scroll = ref;
}} />
<TextInput
multiline={true}
onFocus={(event: any) => {
this.scroll.props.scrollToFocusedInput(ReactNative.findNodeHandle(event.target));
}} />
</KeyboardAwareScrollView>
}
@kylethielk This worked for me, but I had to call without props
this.scroll.scrollToFocusedInput(...);
import { findNodeHandle } from 'react-native';
this.scroll = ref;
}}>
<TextInput
multiline={true}
onFocus={(event: any) => {
this.scroll.props.scrollToFocusedInput(findNodeHandle(event.target))
}}/>
</KeyboardAwareScrollView>
Just encountered this issue on RN 0.56. For anyone finding this I was able to workaround this by hacking it together like so:
render() { <KeyboardAwareScrollView innerRef={ref => { this.scroll = ref; }} /> <TextInput multiline={true} onFocus={(event: any) => { this.scroll.props.scrollToFocusedInput(ReactNative.findNodeHandle(event.target)); }} /> </KeyboardAwareScrollView> }
Just encountered this issue on RN 0.56. For anyone finding this I was able to workaround this by hacking it together like so:
render() { <KeyboardAwareScrollView innerRef={ref => { this.scroll = ref; }} /> <TextInput multiline={true} onFocus={(event: any) => { this.scroll.props.scrollToFocusedInput(ReactNative.findNodeHandle(event.target)); }} /> </KeyboardAwareScrollView> }
onFocus gets not fired when the multiline TextInput changes its height because of user input
extraHeight={100}
enableAutomaticScroll={true}
extraScrollHeight={100}
>
@mitevdev I found the solution.
render() {
<KeyboardAwareScrollView
innerRef={ref => {
this.scroll = ref;
}} />
<TextInput
multiline={true}
onContentSizeChange={(event) => {
this.scroll.props.scrollToEnd();
}} />
</KeyboardAwareScrollView>
}
hmmm how do we reference a ref to scrollview if TextInput lives within a component instead of nicely inline.
Event as a prop I spose
Update: worked with passing event as prop and the line this.scroll.props.scrollToFocusedInput(ReactNative.findNodeHandle(event.target));
plus i set extraHeight={100} on KeyboardAwareFlatList just to bump it up a bit.
So strange: it works as expected on _one_ of my multiline TextInputs, but not on another. I know I'm not adding anything to the discussion. But it has me baffled.
the scrollToFocusedInput takes a second parameter which is extraHeight but it doesn't work seems whatever you pass to it, it will be overwritten in a update method with the default extraHeight or props.
Hey guys,
Just incase this helps anyone I solved this nicely using hooks in the following way:
Layout component (I use React Navigation).avoidKeyboard into that component. If the layout also scrolls then I pass scrollEnabled.react-native-keyboard-aware-scroll-view wrapped in a component called KeyboardAvoidingScrollView. This uses the React context API to provide access to the ref.KeyboardAwareInput component which accesses the ref via the context. If the ref exists then I scrollToFocusedInput in the onContentSizeChange handler using findNodeHandle on the event target.This is working perfectly for me. Here is the code:
Layout.tsx
import React from 'react'
import { View } from 'react-native'
import { makeStyles } from '../styles/makeStyles'
import { KeyboardAvoidingScrollView } from './KeyboardAvoidingScrollView'
interface IProps {
avoidKeyboard?: boolean
scrollEnabled?: boolean
}
export const Layout: React.FunctionComponent<IProps> = ({
avoidKeyboard = false,
scrollEnabled = false,
children,
}) => {
const Container = <View style={styles.container}>{children}</View>
return avoidKeyboard ? (
<KeyboardAvoidingScrollView scrollEnabled={scrollEnabled}>
{Container}
</KeyboardAvoidingScrollView>
) : (
Container
)
}
const styles = makeStyles(theme => ({
container: {
...theme.LayoutContainer.containerStyle,
},
}))
KeyboardAvoidingScrollView.tsx
import React, { createContext, useContext, useRef } from 'react'
import {
KeyboardAwareScrollView,
KeyboardAwareScrollViewProps,
} from 'react-native-keyboard-aware-scroll-view'
import layout from '../constants/Layout'
interface IContext {
scrollViewRef: React.MutableRefObject<KeyboardAwareScrollView>
}
const KeyboardAvoidingScrollViewContext = createContext<IContext>({
scrollViewRef: null,
})
export const useKeyboardAvoidingScrollView = () => {
return useContext(KeyboardAvoidingScrollViewContext)
}
interface IProps extends KeyboardAwareScrollViewProps {
scrollEnabled?: boolean
}
export const KeyboardAvoidingScrollView: React.FunctionComponent<IProps> = ({
scrollEnabled = false,
children,
...scrollViewProps
}) => {
const scrollViewRef = useRef(null)
return (
<KeyboardAwareScrollView
ref={scrollViewRef}
resetScrollToCoords={{ x: 0, y: 0 }}
contentContainerStyle={{ flex: 1 }}
scrollEnabled={scrollEnabled}
extraHeight={layout.window.height / 4}
{...scrollViewProps}
>
<KeyboardAvoidingScrollViewContext.Provider value={{ scrollViewRef }}>
{children}
</KeyboardAvoidingScrollViewContext.Provider>
</KeyboardAwareScrollView>
)
}
KeyboardAwareInput.tsx
import React from 'react'
import { findNodeHandle } from 'react-native'
import { Input, InputProps } from 'react-native-elements'
import { useKeyboardAvoidingScrollView } from '../components/KeyboardAvoidingScrollView'
export const KeyboardAwareInput: React.FunctionComponent<
InputProps
> = inputProps => {
const { scrollViewRef } = useKeyboardAvoidingScrollView()
return (
<Input
{...inputProps}
onContentSizeChange={event => {
if (scrollViewRef && scrollViewRef.current) {
scrollViewRef.current.scrollToFocusedInput(
findNodeHandle(event.target)
)
}
}}
/>
)
}
And then an actual usage example:
ArrangeInPersonMeeting.tsx
_FYI: This is referenced from a TabNavigator, and in this case inside a Modal route_
import React from 'react'
import { NavigationStackScreenComponent } from 'react-navigation-stack'
import { Layout } from '../../../components/Layout'
import { ModalBottomButton } from '../../../components/ModalBottomButton'
import { IMember } from '../../company/interfaces'
import { EnterLocationDetails } from './EnterLocationDetails'
import { ProposedTimes } from './ProposedTimes'
export const ArrangeInPersonMeeting: NavigationStackScreenComponent = ({
navigation,
}) => {
const member: IMember = navigation.dangerouslyGetParent().getParam('member')
return (
<Layout avoidKeyboard>
<ProposedTimes withMember={member} />
<EnterLocationDetails />
<ModalBottomButton
title="Arrange Meeting"
icon={{ type: 'material-community', name: 'calendar-check' }}
/>
</Layout>
)
}
EnterLocationDetails.tsx
import React, { useState } from 'react'
import { View } from 'react-native'
import { CheckBox } from 'react-native-elements'
import { HeaderBar } from '../../../components/HeaderBar'
import { KeyboardAwareInput } from '../../../components/KeyboardAwareInput'
import { Paper } from '../../../components/Paper'
export const EnterLocationDetails: React.FunctionComponent = () => {
const [meetAtOffice, setMeetAtOffice] = useState(false)
const [postalCode, setPostalCode] = useState<string>()
const [details, setDetails] = useState<string>()
return (
<View style={{ flex: 1 }}>
<HeaderBar label="Location" />
<Paper>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}
>
<KeyboardAwareInput
placeholder="Enter Postal Code"
onChangeText={setPostalCode}
value={postalCode}
numberOfLines={1}
maxLength={20}
containerStyle={{
flex: 0.5,
}}
/>
<CheckBox
title="Meet at your office"
checked={meetAtOffice}
onPress={() => setMeetAtOffice(!meetAtOffice)}
containerStyle={{
flex: 0.5,
}}
/>
</View>
<View>
<KeyboardAwareInput
placeholder="Please specify any additional place details or directions..."
onChangeText={setDetails}
value={details}
maxLength={500}
textAlignVertical="top"
numberOfLines={3}
multiline
/>
</View>
</Paper>
</View>
)
}
I hope that helps someone resolve this issue in a clean fashion.
Happy coding!
onContentSizeChange={(event) => {
this.scroll.props.scrollToEnd();
}}
I am able to fix this issue as suggested by @sanddy-man but with little change. Instead of using this.scroll.props.scrollToEnd();, I used this.scrollRef.props.scrollToFocusedInput(findNodeHandle(event.target)); as below:
render() {
<KeyboardAwareScrollView
innerRef={ref => {
this.scroll = ref;
}}
/>
<TextInput
multiline={true}
onContentSizeChange={(event) => {
this.scrollRef.props.scrollToFocusedInput(findNodeHandle(event.target));
}}
/>
</KeyboardAwareScrollView>
}
Thank you @ajaykumar97 this is exactly what I was looking for 馃憤
I'll close this for being very old. Thanks for all the comments 馃樆
A solution seems to be here: https://github.com/APSL/react-native-keyboard-aware-scroll-view/issues/227#issuecomment-554641817
The solution in the comment above does not work for functional components. While one solution was provided using hooks, it is quite involved and is not an easy fix.
Could we keep this issue open, since the expected behavior of the KeyboardAwareScrollView component is to scroll to selected inputs, whether multiline or not? If the current behavior is intended (only scrolling to non-multiline inputs), I suggest the documentation should be updated to make this clear, as it could be a stumbling block for many developers.
Try setting scrollEnabled={false} on TextInput. Allows keyboard-scroll-view take over it seems :)
Most helpful comment
Try setting
scrollEnabled={false}on TextInput. Allows keyboard-scroll-view take over it seems :)