react native - scrolling - ¿Es posible mantener un ScrollView desplazado hacia abajo?
react native scrollview scrollto (12)
Aquí está la solución más simple que pude reunir:
<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
});
}}
/>;
Para una aplicación tipo chat, quiero mantener un componente
ScrollView
desplazado hacia abajo, porque los mensajes más nuevos aparecen debajo de los más antiguos.
¿Podemos ajustar la posición de desplazamiento de un
ScrollView
?
Este método es un poco hacky pero no pude encontrar una mejor manera
- Primero agregue una referencia a su ScrollView.
- En segundo lugar, agregue una vista ficticia antes de cerrar su etiqueta ScrollView
- Obtenga la posición y de esa vista ficticia
- Siempre que desee desplazarse hacia abajo, desplácese hasta la posición de la Vista ficticia
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>
);
}
Esto responde a su pregunta: https://.com/a/39563100/1917250
Debe seguir desplazándose constantemente hasta la parte inferior de la página calculando la altura del contenido menos la altura de su scrollView.
Intente configurar la propiedad contentOffset de la vista de desplazamiento a la altura actual del contenido.
Para lograr lo que necesita, puede hacer esto como parte del evento onScroll. Sin embargo, esto puede provocar una mala experiencia del usuario, por lo que puede resultar más fácil de usar hacer esto solo cuando se agrega un nuevo mensaje.
Luché con esto por un tiempo y finalmente se me ocurrió algo que funcionó realmente bien y sin problemas para mí.
Como muchos, probé
.scrollToEnd
en vano.
La solución que funcionó para mí fue una combinación de
onContentSizeChange
,
onLayout
props y un poco más de pensamiento visual sobre "lo que realmente significaba desplazarse hacia abajo".
La última parte me parece trivial ahora, pero me llevó una eternidad darme cuenta.
Dado que
ScrollView
tiene una altura fija, cuando la altura del contenido supera la altura del contenedor,
prevHeight
el desplazamiento restando el
prevHeight
(altura fija del
ScrollView
) para el
currHeight
(la altura del contenido).
Si puede imaginarlo visualmente, desplazándose a esa diferencia en el eje y, desliza la altura del contenido sobre su contenedor en ese desplazamiento.
Aumenté mi desplazamiento e hice mi altura de contenido actual actual mi altura anterior y seguí calculando un nuevo desplazamiento.
Aquí está el código. Espero que ayude a alguien.
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>
);
}
}
Para
React Native 0.41 y posterior
, puede hacer esto con el método incorporado
scrollToEnd
:
<ScrollView
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=>{
this.scrollView.scrollToEnd({animated: true});
}}>
</ScrollView>
Puede invertir la vista de desplazamiento / lista usando el
módulo
react-native-invertible-scroll-view
, luego simplemente llame a
ref.scrollTo(0)
para desplazarse hacia abajo.
Instalar el módulo:
import InvertibleScrollView from ''react-native-invertible-scroll-view'';
Luego importe el componente:
<InvertibleScrollView inverted
ref={ref => { this.scrollView = ref; }}
onContentSizeChange={() => {
this.scrollView.scrollTo({y: 0, animated: true});
}}
>
{ /* content */ }
</InvertibleScrollView>
Luego use el siguiente JSX en lugar de un
ScrollView
:
<ScrollView ref="scrollView"
onContentSizeChange={(width,height) => this.refs.scrollView.scrollTo({y:height})}> </ScrollView> // OR height - width
Esto funciona porque
react-native-invertible-scroll-view
voltea todo el contenido de la vista.
Tenga en cuenta que los elementos secundarios de la vista también se mostrarán en el orden opuesto a una vista normal: el primer elemento secundario aparecerá en la
parte inferior
.
Supongo que es demasiado tarde para responder, ¡pero tengo un truco!
Si usa
FlatList
, puede habilitar la propiedad
inverted
que vuelve a establecer la
transform scale
en
-1
(que es aceptable para otros componentes de la lista como
ScrollView
...).
Cuando renderiza su
FlatList
con datos, ¡siempre estará en la parte inferior!
Tuve un problema similar, pero después de leer esta página (¡lo que me da dolor de cabeza!) ¡Encuentro este paquete npm muy agradable que simplemente invierte el ListView y facilita todo para una aplicación de chat!
Un poco tarde ... pero mira esta pregunta. Desplazarse hacia la parte superior de ScrollView
ScrollView tiene un método "scrollTo".
Use onContentSizeChange para realizar un seguimiento de la parte inferior Y de la vista de desplazamiento (altura)
https://facebook.github.io/react-native/docs/scrollview.html#oncontentsizechange
var _scrollToBottomY
<ScrollView
onContentSizeChange={(contentWidth, contentHeight)=>{
_scrollToBottomY = contentHeight;
}}>
</ScrollView>
luego use el nombre de referencia de la vista de desplazamiento como
this.refs.scrollView.scrollTo(_scrollToBottomY);
prueba esta solución
xcode 10.0
RN: 56.0.0
npm install --save react-native-invertible-scroll-view