Impedire che la Flatlist invertita scorra verso il basso quando vengono aggiunti nuovi elementi

voti
41

Sto costruendo un'applicazione di chat, utilizzando un'applicazione Flatlist. Aggiungo nuovi elementi in cima alla lista quando onEndReachedviene chiamata e tutto funziona bene.

Il problema è che se si aggiungono elementi in fondo alla lista, questa scorre istantaneamente in fondo alla lista. Ciò significa che l'utente deve scorrere indietro per leggere i messaggi appena aggiunti (il che è terribile).

Ho provato a chiamarescrollToOffsetonContentSizeChange, ma questo ha un ritardo di un secondo in cui lo scroll salta avanti e indietro.

Come posso far sì che la lista si comporti allo stesso modo quando aggiungo elementi in alto E in basso, mantenendo gli stessi messaggi sullo schermo invece di mostrare quelli nuovi?

È pubblicato 26/05/2020 alle 14:44
fonte dall'utente
In altre lingue...                            


3 risposte

voti
0

Avete provato a usare keyExtractor? Può aiutare a reagire evitando il re-render, quindi provate a usare chiavi uniche per ogni articolo. potete saperne di più qui: https://reactnative.dev/docs/flatlist#keyextractor

Risposto il 26/05/2020 a 18:35
fonte dall'utente

voti
0

ecco la demo: https://snack.expo.io/@nomi9995/flatlisttest

Soluzione 1:

utilizzare i puntelli maintainVisibleContentPosition per prevenire l'autoscorrimento in IOS, ma purtroppo non funziona su Android.

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

Soluzione 2:

Ho trovato un'altra soluzione mantenendo l'ultimo offset y con onScroll e salvando anche l'altezza del contenuto prima e dopo l'aggiunta di nuovi elementi con onContentSizeChange e calcolando la differenza di altezza del contenuto, e impostando il nuovo offset y all'ultimo offset y della differenza di altezza del contenuto!

Risposto il 28/05/2020 a 15:36
fonte dall'utente

voti
0

Qui aggiungo un nuovo articolo sopra e sotto in una Flatlist invertita.

enter image description here

Spero che possiate confrontare le vostre esigenze con il codice campione fornito :)

Codice completo:

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,
  },
});
Risposto il 30/05/2020 a 14:55
fonte dall'utente

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