Предотвратить прокрутку перевернутого плоского списка вниз при добавлении новых элементов - PullRequest
5 голосов
/ 26 мая 2020

Я создаю приложение для чата, используя перевернутый Flatlist. Я добавляю новые элементы в начало списка, когда вызывается onEndReached, и все работает нормально.

Проблема в том, что при добавлении элементов в конец он мгновенно прокручивается в конец списка. Это означает, что пользователь должен прокрутить назад, чтобы прочитать только что добавленные сообщения (что ужасно).

Я пытался позвонить scrollToOffset в onContentSizeChange, но это имеет задержку в одну секунду где прокрутка прыгает вперед и назад.

Как я могу заставить список вести себя точно так же, когда я добавляю элементы вверху И внизу , вместо этого сохраняя те же сообщения на экране показывать новые?

Ответы [ 3 ]

2 голосов
/ 28 мая 2020

вот демонстрация: https://snack.expo.io/@nomi9995 / flatlisttest

Решение 1:

используйте keepVisibleContentPosition props для предотвращения автоматическая прокрутка в IOS, но, к сожалению, она не работает на android.

<FlatList
  ref={(ref) => { this.chatFlatList = ref; }}
  style={styles.flatList}
  data={this.state.items}
  renderItem={this._renderItem}
  maintainVisibleContentPosition={{
     minIndexForVisible: 0,
  }}
/>

Решение 2:

Я нашел другой обходной путь, сохранив последнее смещение по y с помощью onScroll , а также сохранить высоту содержимого до и после добавления новых элементов с помощью onContentSizeChange и вычислить разницу в высоте содержимого, а также установить новое смещение по оси Y на последнее смещение по оси Y + разницу в высоте содержимого!

0 голосов
/ 30 мая 2020

Здесь я добавляю новый элемент сверху и снизу в инвертированный плоский список .

enter image description here

Надеюсь, вы сможете сравните свои требования с предоставленным образцом кода :)

Полный код:


import React, {Component} from 'react';
import {
  SafeAreaView,
  View,
  FlatList,
  StyleSheet,
  Text,
  Button,
  Platform,
  UIManager,
  LayoutAnimation,
} from 'react-native';

if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
  }
}

const getRandomColor = () => {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
};

const DATA = [
  getRandomColor(),
  getRandomColor(),
  getRandomColor(),
  getRandomColor(),
  getRandomColor(),
];

export default class App extends Component {
  scrollValue = 0;
  append = true;

  state = {
    data: DATA,
  };

  addItem = (top) => {
    const {data} = this.state;
    let newData;
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    if (top) {
      newData = [...data, getRandomColor()];
      this.setState({data: newData});
    } else {
      newData = [getRandomColor(), ...data];
      this.setState({data: newData});
    }
  };

  shouldComponentUpdate() {
    return this.scrollValue === 0 || this.append;
  }

  onScrollBeginDrag = () => {
    this.append = true;
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    this.setState({});
  };

  render() {
    const {data} = this.state;
    return (
      <SafeAreaView style={styles.container}>
        <Button title="ADD ON TOP" onPress={() => this.addItem(true)} />
        <FlatList
          data={data}
          onScrollBeginDrag={this.onScrollBeginDrag}
          renderItem={({item}) => <Item item={item} />}
          keyExtractor={(item) => item}
          inverted
          onScroll={(e) => {
            this.append = false;
            this.scrollValue = e.nativeEvent.contentOffset.y;
          }}
        />
        <Button title="ADD ON BOTTOM" onPress={() => this.addItem(false)} />
      </SafeAreaView>
    );
  }
}

function Item({item}) {
  return (
    <View style={[styles.item, {backgroundColor: item}]}>
      <Text style={styles.title}>{item}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    height: 100,
  },
  title: {
    fontSize: 32,
  },
});

0 голосов
/ 26 мая 2020

Вы пробовали использовать keyExtractor? Это может помочь избежать повторного рендеринга, поэтому попробуйте использовать уникальные ключи для каждого элемента. вы можете прочитать об этом здесь: https://reactnative.dev/docs/flatlist#keyextractor

...