W przypadku aplikacji podobnej do czatu chcę, aby ScrollViewkomponent był przewijany do dołu, ponieważ najnowsze wiadomości pojawiają się pod starszymi. Czy możemy dostosować pozycję przewijania ScrollView?
W przypadku aplikacji podobnej do czatu chcę, aby ScrollViewkomponent był przewijany do dołu, ponieważ najnowsze wiadomości pojawiają się pod starszymi. Czy możemy dostosować pozycję przewijania ScrollView?
Odpowiedzi:
W przypadku React Native 0.41 i nowszych możesz to zrobić za pomocą wbudowanej scrollToEndmetody:
<ScrollView
ref={ref => {this.scrollView = ref}}
onContentSizeChange={() => this.scrollView.scrollToEnd({animated: true})}>
</ScrollView>
rootinaczej, scrollToEnd jest niezdefiniowana. tj.this.scrollView.root.scrollToEnd
rootrzeczywistości generuje niezdefiniowany błąd.
ref={ref => {this.scrollView = ref}}ponieważ nie chcesz zwracać zadania
Użyj onContentSizeChange, aby śledzić dolne Y widoku przewijania (wysokość)
https://facebook.github.io/react-native/docs/scrollview.html#oncontentsizechange
var _scrollToBottomY
<ScrollView
onContentSizeChange={(contentWidth, contentHeight)=>{
_scrollToBottomY = contentHeight;
}}>
</ScrollView>
następnie użyj nazwy referencyjnej widoku przewijania, np
this.refs.scrollView.scrollTo(_scrollToBottomY);
Oto najprostsze rozwiązanie, jakie mogłem wymyślić:
<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
});
}}
/>;
Dla każdego, kto pisze komponent funkcyjny, który może używać hooka,
import React, { useRef } from 'react';
import { ScrollView } from 'react-native';
const ScreenComponent = (props) => {
const scrollViewRef = useRef();
return (
<ScrollView
ref={scrollViewRef}
onContentSizeChange={() => scrollViewRef.current.scrollToEnd({ animated: true })}
/>
);
};
Na wypadek, gdyby ktoś w 2020 roku lub później zastanawiał się, jak to osiągnąć za pomocą funkcjonalnych komponentów. Oto jak zrobiłem:
ref={ref => scrollView = ref }
onContentSizeChange={() => scrollView.scrollToEnd({ animated: true })}>
wypróbuj to rozwiązanie
xcode 10.0
RN: 56,0,0
<ScrollView ref="scrollView"
onContentSizeChange={(width,height) => this.refs.scrollView.scrollTo({y:height})}> </ScrollView> // OR height - width
ref=? wydaje się być reliktem
Możesz odwrócić widok przewijania / listy za pomocą react-native-invertible-scroll-viewmodułu , a następnie po prostu zadzwoń, ref.scrollTo(0)aby przewinąć do dołu.
Zainstaluj moduł:
npm install --save react-native-invertible-scroll-view
Następnie zaimportuj komponent:
import InvertibleScrollView from 'react-native-invertible-scroll-view';
Następnie użyj następującego JSX zamiast a ScrollView:
<InvertibleScrollView inverted
ref={ref => { this.scrollView = ref; }}
onContentSizeChange={() => {
this.scrollView.scrollTo({y: 0, animated: true});
}}
>
{ /* content */ }
</InvertibleScrollView>
To działa, ponieważ react-native-invertible-scroll-viewodwraca zawartość całego widoku. Zwróć uwagę, że elementy podrzędne widoku będą również renderowane w odwrotnej kolejności do normalnego widoku - pierwsze dziecko pojawi się na dole .
Właściwie odpowiedź @Aniruddha nie działa dla mnie, ponieważ używam, "react-native": "0.59.8"a this.scrollView.root.scrollToEndtakże jest niezdefiniowana
ale wymyśliłem to i to działa this.scrollView.scrollResponderScrollToEnd({animated: true});
Jeśli używasz, 0.59.8to zadziała LUB jeśli używasz późniejszej wersji i to działa dla Ciebie. dodaj wersje w tej odpowiedzi, aby inni nie mieli problemów.
Pełny kod tutaj
<ScrollView
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.scrollView.scrollResponderScrollToEnd({animated: true});
}}>
</ScrollView>
Ta metoda jest trochę hakerska, ale nie mogłem znaleźć lepszego sposobu
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>
);
}
scrollToBottomsprawia , że takie podejście jest przestarzałe w nowszych wersjach React Native.
To odpowiada na Twoje pytanie: https://stackoverflow.com/a/39563100/1917250
Musisz stale przewijać do dołu strony, obliczając wysokość zawartości minus wysokość jej scrollView.
Jeśli używasz TypeScript, musisz to zrobić
interface Props extends TextInputProps {
scrollRef?: any;
}
export class Input extends React.Component<Props, any> {
scrollRef;
constructor(props) {
this.scrollRef = React.createRef();
}
<ScrollView
ref={ref => (this.scrollRef = ref)}
onContentSizeChange={() => {
this.scrollRef.scrollToEnd();
}}
>
</ScrollView>
Przez chwilę z tym walczyłem i w końcu wymyśliłem coś, co działało naprawdę dobrze i gładko. Jak wielu, .scrollToEndbezskutecznie próbowałem . Rozwiązanie że pracował dla mnie było połączenie onContentSizeChange,onLayout rekwizytów i trochę więcej myślenia wizualnie o „co przewijanie do dołu” naprawdę znaczy. Ostatnia część wydaje mi się teraz trywialna, ale zajęło mi całe wieki, zanim to zrozumiałem.
Biorąc pod uwagę, że ScrollViewma stałą wysokość, gdy wysokość zawartości przekracza wysokość kontenera, obliczyłem przesunięcie, odejmując prevHeight(stałą wysokość ScrollView) dla currHeight(wysokość zawartości). Jeśli możesz sobie to wyobrazić wizualnie, przewijanie do tej różnicy w osi Y przesuwa wysokość zawartości nad kontenerem o to przesunięcie. Zwiększyłem swoje przesunięcie i ustawiłem obecną wysokość zawartości na poprzednią wysokość i kontynuowałem obliczanie nowego przesunięcia.
Oto kod. Mam nadzieję, że to komuś pomoże.
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>
);
}
}
Myślę, że jest za późno na odpowiedź, ale udało mi się jeden hack! Jeśli używasz FlatList, możesz włączyć invertedwłaściwość, która powraca do ustawienia transform scalena -1(co jest akceptowalne w przypadku innych składników listy, takich jak ScrollView...). Kiedy renderujesz swoje FlatListdane, zawsze będzie to na dole!
Spróbuj ustawić właściwość contentOffset widoku przewijania na bieżącą wysokość treści.
Aby osiągnąć to, czego potrzebujesz, możesz to zrobić w ramach wydarzenia onScroll. Może to jednak niekorzystnie wpłynąć na wrażenia użytkownika, więc bardziej przyjazne dla użytkownika może być robienie tego tylko po dołączeniu nowej wiadomości.
ScrollViewdół do poniżej całej zawartości, a nie tylko przewijanie w dół.
Miałem podobny problem, ale po przeczytaniu tej strony (co przyprawia mnie o ból głowy!) Znalazłem ten bardzo fajny pakiet npm, który po prostu odwraca ListView i ułatwia aplikację do czatu !!
ScrollView, a nie ListView).
Trochę późno ... ale spójrz na to pytanie. Przewiń do góry ScrollView
ScrollView ma metodę „scrollTo”.