greW
greW

Reputation: 1338

react-native scrollView - scrollToEnd - on Android

I'm trying to call a function that will fire upon onFoucs on TextInput that will scroll the scrollView all the way down (using scrollToEnd())

so this is my class component

class MyCMP extends Component {

  constructor(props) {
    super(props);
    this.onInputFocus = this.onInputFocus.bind(this);
  }

  onInputFocus() {
    setTimeout(() => {
      this.refs.scroll.scrollToEnd();
      console.log('done scrolling');
    }, 1);
  }

  render() {
    return (
      <View>
        <ScrollView ref="scroll">
          { /* items */ }
        </ScrollView>
        <TextInput onFocus={this.onInputFocus} />
      </View>
    );
  }
}

export default MyCMP;

the component above works and it does scroll but it takes a lot of time ... I'm using setTimeout because without it its just going down the screen without calculating the keybaord's height so it not scrolling down enough, even when I keep typing (and triggering that focus on the input) it still doesn't scroll all the way down.

I'm dealing with it some good hours now, I did set the windowSoftInputMode to adjustResize and I did went through some modules like react-native-keyboard-aware-scroll-view or react-native-auto-scroll but none of them really does the work as I need it.

any direction how to make it done the right way would be really appreciated. thanks!

Upvotes: 5

Views: 17510

Answers (2)

Cyrus Zei
Cyrus Zei

Reputation: 2660

If you have a large dataset React Native docs is telling you to go with FlatList.

To get it to scroll to bottom this is what worked for me

<FlatList
  ref={ref => (this.scrollView = ref)}
  onContentSizeChange={() => {
    this.scrollView.scrollToEnd({ animated: true, index: -1 }, 200);
  }}
/>

Upvotes: 5

bennygenel
bennygenel

Reputation: 24680

Rather than using a setTimeout you use Keyboard API of react-native. You add an event listener for keyboard show and then scroll the view to end. You might need to create some logic on which input is focused if you have more than one input in your component but if you only have one you can just do it like the example below.

Another good thing to do is changing your refs to functional ones since string refs are considered as legacy and will be removed in future releases of react. More info here.

class MyCMP extends Component {

  constructor(props) {
    super(props);
    this.scroll = null;
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this));
  }

  componentWillUnmount () {
    this.keyboardDidShowListener.remove();
  }

  _keyboardDidShow() {
    this.scroll.scrollToEnd();
  }

  render() {
    return (
      <View>
        <ScrollView ref={(scroll) => {this.scroll = scroll;}}>
          { /* items */ }
        </ScrollView>
        <TextInput />
      </View>
    );
  }
}

export default MyCMP;

Upvotes: 7

Related Questions