Предотвратить прокрутку перевернутого Flatlist вниз при добавлении новых элементов

голоса
41

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

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

Я пытался дозвонитьсяscrollToOffsetonContentSizeChange, но у него задержка в одну секунду, когда свиток прыгает туда-сюда.

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

Задан 26/05/2020 в 14:44
источник пользователем
На других языках...                            


3 ответов

голоса
0

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

Ответил 26/05/2020 в 18:35
источник пользователем

голоса
0

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

Решение 1:

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

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

Решение 2:

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

Ответил 28/05/2020 в 15:36
источник пользователем

голоса
0

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

enter image description here

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

Полный код:

import React, {useState, createRef} from 'react';
import {
  SafeAreaView,
  View,
  FlatList,
  StyleSheet,
  Text,
  Button,
  Platform,
  UIManager,
} 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(),
];

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

let scrollValue = 0;
let itemHeight = 100;

export default function App() {
  const [data, setData] = useState(DATA);
  let flatList = createRef();

  const addItem = (top) => {
    let newData;
    if (top) {
      newData = [...data, getRandomColor()];
      setData(newData);
    } else {
      newData = [getRandomColor(), ...data];
      setData(newData);
      if (scrollValue > itemHeight) {
        flatList.current.scrollToOffset({
          offset: scrollValue + itemHeight,
          animated: false,
        });
      }
    }
  };

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

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    height: itemHeight,
  },
  title: {
    fontSize: 32,
  },
});
Ответил 30/05/2020 в 14:55
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more