Pour une application de type chat, je souhaite faire défiler un composant ScrollView
vers le bas, car les messages les plus récents apparaissent sous les anciens. Pouvons-nous ajuster la position de défilement d'une ScrollView
?
Pour React Native 0.41 et versions ultérieures, vous pouvez le faire avec la méthode scrollToEnd
intégrée:
<ScrollView
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.scrollView.scrollToEnd({animated: true});
}}>
</ScrollView>
Utilisez onContentSizeChange pour garder une trace du Y inférieur de la vue de défilement (hauteur)
https://facebook.github.io/react-native/docs/scrollview.html#oncontentsizechange
var _scrollToBottomY
<ScrollView
onContentSizeChange={(contentWidth, contentHeight)=>{
_scrollToBottomY = contentHeight;
}}>
</ScrollView>
puis utilisez le nom de référence de la vue de défilement comme
this.refs.scrollView.scrollTo(_scrollToBottomY);
Voici la solution la plus simple que je pourrais trouver:
<ListView
ref={ref => (this.listView = ref)}
onLayout={event => {
this.listViewHeight = event.nativeEvent.layout.height;
}}
onContentSizeChange={() => {
this.listView.scrollTo({
y: this.listView.getMetrics().contentLength - this.listViewHeight
});
}}
/>;
Vous pouvez inverser la vue de défilement/liste à l’aide du module react-native-invertible-scroll-view
, puis appelez simplement ref.scrollTo(0)
pour faire défiler vers le bas.
Installez le module:
npm install --save react-native-invertible-scroll-view
Importez ensuite le composant:
import InvertibleScrollView from 'react-native-invertible-scroll-view';
Ensuite, utilisez le fichier JSX suivant au lieu de ScrollView
:
<InvertibleScrollView inverted
ref={ref => { this.scrollView = ref; }}
onContentSizeChange={() => {
this.scrollView.scrollTo({y: 0, animated: true});
}}
>
{ /* content */ }
</InvertibleScrollView>
Cela fonctionne parce que react-native-invertible-scroll-view
retourne le contenu de la vue entière. Notez que les enfants de la vue seront également rendus dans l'ordre inverse de la vue normale - le premier enfant apparaîtra au bottom.
Cette méthode est un peu compliquée mais je ne pouvais pas trouver un meilleur moyen
var footerY; //Y position of the dummy view
render() {
return (
<View>
<ScrollView
ref='_scrollView'>
// This is where all the things that you want to display in the scroll view goes
// Below is the dummy View
<View onLayout={(e)=> {
footerY = e.nativeEvent.layout.y;
}}/>
</ScrollView>
//Below is the button to scroll to the bottom
<TouchableHighlight
onPress={() => { this.refs._scrollView.scrollTo(footerY); }}>
<Text>Scroll to Bottom</Text>
</TouchableHighlight>
</View>
);
}
essayez cette solution
xcode 10.0
RN: 56.0.0
<ScrollView ref="scrollView"
onContentSizeChange={(width,height) => this.refs.scrollView.scrollTo({y:height})}> </ScrollView> // OR height - width
Cela aidera peut-être quelqu'un qui a des problèmes similaires à gérer des éléments d'une liste.
Cela fera défiler jusqu'au dernier élément de la liste. Je l'utilise dans une application de messagerie.
<FlatList
data={data.messages}
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.scrollView.scrollToIndex({index: data.messages.length - 2});
}}
renderItem={({item}) => this.renderItem(item)}
/>
Je me suis battu avec ça pendant un moment et finalement j'ai trouvé quelque chose qui a vraiment bien fonctionné et qui s'est bien déroulé pour moi. Comme beaucoup, j'ai essayé .scrollToEnd
sans succès. La solution qui a fonctionné pour moi était une combinaison d'accessoires onContentSizeChange
, onLayout
et un peu plus réfléchissant visuellement à «ce que faire défiler vers le bas» signifiait vraiment. La dernière partie me semble banale maintenant, mais il me fallut une éternité pour comprendre.
Étant donné que la ScrollView
a une hauteur fixe, lorsque la hauteur du contenu dépasse celle du conteneur, j'ai calculé le décalage en soustrayant la prevHeight
(hauteur fixe de la ScrollView
) pour la currHeight
(hauteur du contenu). Si vous pouvez l'imaginer visuellement, en faisant défiler la différence d'axe des y jusqu'à la différence, faites glisser la hauteur du contenu sur son conteneur de ce décalage. J'ai incrémenté mon décalage et transformé le contenu actuel en hauteur en hauteur précédente tout en calculant un nouveau décalage.
Voici le code. J'espère que ça aide quelqu'un.
class ChatRoomCorrespondence extends PureComponent {
currHeight = 0;
prevHeight = 0;
scrollHeight = 0;
scrollToBottom = () => {
this.refs.scrollView.getScrollResponder().scrollResponderScrollTo({
x: 0,
y: this.scrollHeight,
animated: true
});
};
render() {
return (
<ScrollView
style={Styles.container}
ref="scrollView"
onContentSizeChange={(w, h) => {
this.currHeight = h;
if (
this.prevHeight > 0 &&
this.currHeight - this.scrollHeight > this.prevHeight
) {
this.scrollHeight += this.currHeight - this.prevHeight;
console.log("--------------------------------------------");
console.log("Curr: ", this.currHeight);
console.log("Prev: ", this.prevHeight);
console.log("Scroll: ", this.scrollHeight);
this.prevHeight = this.currHeight;
console.log("PREV: ", this.prevHeight);
console.log("--------------------------------------------");
this.scrollToBottom();
}
}}
onLayout={ev => {
// Fires once
const fixedContentHeight = ev.nativeEvent.layout.height;
this.prevHeight = fixedContentHeight;
}}
>
<FlatList
data={this.props.messages}
renderItem={({ item }) => (
<ChatMessage
text={item.text}
sender={item.sender}
time={item.time}
username={this.props.username}
/>
)}
keyExtractor={(item, index) => index.toString()}
/>
</ScrollView>
);
}
}
J'imagine qu'il est trop tard pour répondre, mais j'en ai un! Si vous utilisez FlatList
, vous pouvez activer la propriété inverted
qui revient à définir transform scale
sur -1
(acceptable pour d'autres composants de liste tels que ScrollView
... ). Lorsque vous restituez votre FlatList
avec des données, il sera toujours en bas!
Cela répond à votre question: https://stackoverflow.com/a/39563100/1917250
Vous devez constamment faire défiler la page jusqu'en bas en calculant la hauteur du contenu moins la hauteur de son scrollView.