Scroll to end of FlatList after displaying the keyboard

Andrew Arthur picture Andrew Arthur · May 17, 2017 · Viewed 27.9k times · Source

I have a FlatList inside a KeyboardAvoidingView. When the keyboard is displayed I would like to scroll to the end of the FlatList.

I am listening for the 'keyboardDidShow' event which does get fired, but it may be fired too early as the FlatList is not scrolled to the end after calling scrollToEnd.

I have looked into the onLayout event of KeyboardAvoidingView however just setting the onLayout event to trigger a function seems to stop the KeyboardAvoidingView from adjusting it's size when the Keyboard is shown.

<KeyboardAvoidingView behavior='padding' style={{ flex: 1}} onLayout={this._scrollEnd}>

Code:

import React from 'react';
import {Image, Linking, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View, Button, Alert, FlatList, TextInput, KeyboardAvoidingView, Keyboard} from 'react-native';
import { MonoText } from '../components/StyledText';

export default class HomeScreen extends React.Component {
  constructor() {
    super();
    this.state = {
      messages: getMessages()
    };

    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._scrollEnd);
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidHide', this._scrollEnd);
  }

  _scrollEnd = (evt) => {
    this.refs.flatList1.scrollToEnd();
  }

  render() {
    return (
      <KeyboardAvoidingView behavior='padding' style={{ flex: 1}} >
        <FlatList
          style={{ flex:1}}
          ref="flatList1"
          data={this.state.messages}
          renderItem={({ item }) => <Text>{item.text}</Text>}
        />
      </KeyboardAvoidingView>
    );
  }
}

Answer

Anthony De Smet picture Anthony De Smet · Jan 1, 2018

I'm making a chat component and I want about the same things. Did it like this:

<FlatList
   ref={ref => this.flatList = ref}
   onContentSizeChange={() => this.flatList.scrollToEnd({animated: true})}
   onLayout={() => this.flatList.scrollToEnd({animated: true})}
   ...
/>

Keyboard popping up triggers a layout, so that's fixed. New chat messages arriving trigger content changes, so it also scrolls to the bottom (which is what I wanted for my chat window)