stackunderflow
stackunderflow

Reputation: 1796

React Native - Keyboard avoiding not working if ScrollView is not at the top of the screen

<View>
    <View style = {{height : X}}></View>
    <ScrollView>
        <KeyboardAvoidingView>
            <View style = {{height : 350}}></View>
            <TextInput/>
            <View style = {{height : 500}}></View>
        </KeyboardAvoidingView>
    </ScrollView>
</View>

When I tap on the TextInput, it is scrolled upward but stop at the position of below where it is supposed to be as much as X, which means it is still hidden under the keyboard.

Actually the problem is not about KeyboardAvoidingView because it also happens without the use of it

Upvotes: 1

Views: 7196

Answers (2)

stackunderflow
stackunderflow

Reputation: 1796

render() {
    var a = [];
    for(var i =1; i< 100; i++) a.push(i);
    return (
        <View>
            <Button title = 'Scroll' onPress = {() => this.refs.scroll.scrollTo({x: 0, y: 0, animated: true})}/>
            <ScrollView ref = 'scroll'>{a.map((item, index) => (<TextInput style = {{height : 10 + (Math.floor(Math.random() * 10) * 5)}}
                placeholder = {item + ''}
                onFocus = {() => {
                    this.refs.scroll.scrollTo({x : 0, y : this.y[index], animated : true});
                }}
                onLayout = {event => {
                    this.y[index] = event.nativeEvent.layout.y;
                }}
            />))}</ScrollView>
        </View>
    );
}

Using this solution, there are 2 drawbacks exist which raise other problems require solutions

  • Not applicable in case the TextInput is inside a FlatList or perhaps certain components which contain TextInput indirectly. In this case, event.nativeEvent.layout.y will always return 0. No problem for multilevel ScrollView. Temporarily the solution is to avoid placing the TextInput inside a prop component
  • The TextInput's offset is relative to wrapper component if it's not the ScrollView. Scroll distance must be the summation of TextInput's offset and wrapper's offset if the wrapper is not at the top of ScrollView. Since a parent's post-layout data cannot be passed to a child directly via prop before it is rendered, the TextInput must get the wrapper's offset in it's onFocus handler
  • Default buggy keyboard avoiding sometimes take action after onFocus, cancelling onFocus's effect. The temporary solution is to use setTimeout to delay onFocus action for at least 200 milliseconds

Upvotes: 0

Haider Ali
Haider Ali

Reputation: 1285

This is what I did it to resolve this issue

<KeyboardAvoiding behavior={'padding'} keyboardVerticalOffset={64} style={styles.container}>
        <View style={styles.container}>
          <ScrollView keyboardShouldPersistTaps="always">
            <View style = {{height : 350}}></View>
            <TextInput/>
            <View style = {{height : 500}}></View>
          </ScrollView>
        </View>
      </KeyboardAvoiding>

container: {
    flex: 1,
    alignItems: 'center',
  }

and this is the KeyboardAvoiding class

import React from 'react'
import { Platform, KeyboardAvoidingView as ReactNativeKeyboardAvoidingView } from 'react-native'

class KeyboardAvoidingView extends React.Component {
  render() {
    if (Platform.OS === 'ios') {
      return (
        <ReactNativeKeyboardAvoidingView behavior={'padding'} {...this.props}>
          {this.props.children}
        </ReactNativeKeyboardAvoidingView>
      )
    }

    return this.props.children
  }
}

KeyboardAvoidingView.propTypes = {
  children: React.PropTypes.element,
}

module.exports = KeyboardAvoidingView

Hope this helps.

Upvotes: 4

Related Questions