vertical react pagingenabled horizontal and ios reactjs react-native

ios - pagingenabled - scrollview keyboard react native



Obtener la posiciĆ³n de desplazamiento actual de ScrollView en React Native (8)

Así es como terminó obteniendo la posición de desplazamiento actual en vivo desde la vista. Todo lo que estoy haciendo es usar el detector de eventos on scroll y scrollEventThrottle. Luego lo paso como un evento para manejar la función de desplazamiento que hice y actualizo mis accesorios.

export default class Anim extends React.Component { constructor(props) { super(props); this.state = { yPos: 0, }; } handleScroll(event){ this.setState({ yPos : event.nativeEvent.contentOffset.y, }) } render() { return ( <ScrollView onScroll={this.handleScroll.bind(this)} scrollEventThrottle={16} /> ) } }

¿Es posible obtener la posición de desplazamiento actual o la página actual de un componente <ScrollView> en React Native?

Entonces algo como:

<ScrollView horizontal={true} pagingEnabled={true} onScrollAnimationEnd={() => { // get this scrollview''s current page or x/y scroll position }}> this.state.data.map(function(e, i) { <ImageCt key={i}></ImageCt> }) </ScrollView>



Descargo de responsabilidad: lo que sigue es principalmente el resultado de mi propia experimentación en React Native 0.50. En la documentación de ScrollView , actualmente falta mucha de la información que se cubre a continuación; por ejemplo, onScrollEndDrag está completamente indocumentado. Dado que todo aquí depende de un comportamiento indocumentado, desafortunadamente no puedo prometer que esta información seguirá siendo correcta dentro de un año o incluso un mes.

Además, todo lo que se muestra a continuación supone una vista de desplazamiento puramente vertical cuyo desplazamiento y nos interesa; La traducción a las compensaciones x , si es necesario, es un ejercicio fácil para el lector.

Varios controladores de eventos en un ScrollView toman un event y le permiten obtener la posición de desplazamiento actual a través de event.nativeEvent.contentOffset.y . Algunos de estos controladores tienen un comportamiento ligeramente diferente entre Android e iOS, como se detalla a continuación.

onScroll

En Android

Dispara cada cuadro mientras el usuario se desplaza, en cada cuadro mientras la vista de desplazamiento se desliza después de que el usuario lo suelta, en el cuadro final cuando la vista de desplazamiento se detiene, y también cada vez que el desplazamiento de la vista de desplazamiento cambia como resultado de su cuadro cambiante (por ejemplo, debido a la rotación de paisaje a retrato).

En iOS

Se dispara mientras el usuario arrastra o mientras la vista de desplazamiento se desliza, a cierta frecuencia determinada por scrollEventThrottle y como máximo una vez por cuadro cuando scrollEventThrottle={16} . Si el usuario suelta la vista de desplazamiento mientras tiene suficiente impulso para deslizarse, el controlador onScroll también se activará cuando se onScroll después de deslizarse. Sin embargo, si el usuario arrastra y luego suelta la vista de desplazamiento mientras está parado, no se garantiza que onScroll dispare para la posición final a menos que scrollEventThrottle se haya configurado de manera que onScroll dispare cada cuadro de desplazamiento.

Hay un costo de rendimiento para configurar scrollEventThrottle={16} que se puede reducir estableciéndolo en un número mayor. Sin embargo, esto significa que onScroll no disparará cada cuadro.

onMomentumScrollEnd

Se dispara cuando la vista de desplazamiento se detiene después del deslizamiento. No se dispara en absoluto si el usuario suelta la vista de desplazamiento mientras está parado de modo que no se desliza.

onScrollEndDrag

Se activa cuando el usuario deja de arrastrar la vista de desplazamiento, independientemente de si la vista de desplazamiento se deja estacionaria o comienza a deslizarse.

Dadas estas diferencias de comportamiento, la mejor manera de realizar un seguimiento del desplazamiento depende de sus circunstancias precisas. En el caso más complicado (debe ser compatible con Android e iOS, incluido el manejo de cambios en el marco de ScrollView debido a la rotación, y no desea aceptar la penalización de rendimiento en Android al configurar scrollEventThrottle en 16), y necesita para manejar los cambios en el contenido en la vista de desplazamiento también, entonces es un verdadero desastre.

El caso más simple es si solo necesita manejar Android; solo usa onScroll :

<ScrollView onScroll={event => { this.yOffset = event.nativeEvent.contentOffset.y }} >

Para admitir adicionalmente iOS, si está contento de disparar el controlador onScroll cada cuadro y aceptar las implicaciones de rendimiento de eso, y si no necesita manejar los cambios de cuadro, entonces es solo un poco más complicado:

<ScrollView onScroll={event => { this.yOffset = event.nativeEvent.contentOffset.y }} scrollEventThrottle={16} >

Para reducir la sobrecarga de rendimiento en iOS y al mismo tiempo garantizar que scrollEventThrottle cualquier posición en la que se establezca la vista de desplazamiento, podemos aumentar scrollEventThrottle y además proporcionar un controlador onScrollEndDrag :

<ScrollView onScroll={event => { this.yOffset = event.nativeEvent.contentOffset.y }} onScrollEndDrag={event => { this.yOffset = event.nativeEvent.contentOffset.y }} scrollEventThrottle={160} >

Pero si queremos manejar los cambios en el marco (por ejemplo, porque permitimos que el dispositivo gire, cambiando la altura disponible para el marco de la vista de desplazamiento) y / o los cambios de contenido, entonces debemos implementar adicionalmente tanto onContentSizeChange como en onLayout para realizar un seguimiento de la altura tanto del marco de la vista de desplazamiento como de su contenido, y así calcular continuamente el desplazamiento máximo posible e inferir cuando el desplazamiento se ha reducido automáticamente debido a un cambio de tamaño de contenido o marco:

<ScrollView onLayout={event => { this.frameHeight = event.nativeEvent.layout.height; const maxOffset = this.contentHeight - this.frameHeight; if (maxOffset < this.yOffset) { this.yOffset = maxOffset; } }} onContentSizeChange={(contentWidth, contentHeight) => { this.contentHeight = contentHeight; const maxOffset = this.contentHeight - this.frameHeight; if (maxOffset < this.yOffset) { this.yOffset = maxOffset; } }} onScroll={event => { this.yOffset = event.nativeEvent.contentOffset.y; }} onScrollEndDrag={event => { this.yOffset = event.nativeEvent.contentOffset.y; }} scrollEventThrottle={160} >

Sí, es bastante horrible. Tampoco estoy 100% seguro de que siempre funcionará correctamente en los casos en que cambie simultáneamente el tamaño del marco y el contenido de la vista de desplazamiento. Pero es lo mejor que se me ocurre, y hasta que esta característica se agregue dentro del marco en sí , creo que es lo mejor que cualquiera puede hacer.


En cuanto a la página, estoy trabajando en un componente de orden superior que utiliza básicamente los métodos anteriores para hacer exactamente esto. En realidad, lleva solo un poco de tiempo llegar a las sutilezas, como el diseño inicial y los cambios de contenido. No afirmaré haberlo hecho ''correctamente'', pero en cierto sentido consideraría la respuesta correcta para usar un componente que lo haga con cuidado y coherencia.

Ver: react-native-paged-scroll-view . ¡Me encantaría recibir comentarios, incluso si es que lo he hecho todo mal!


La respuesta de Brad Oyler es correcta. Pero solo recibirá un evento. Si necesita obtener actualizaciones constantes de la posición de desplazamiento, debe configurar el accesorio scrollEventThrottle , así:

<ScrollView onScroll={this.handleScroll} scrollEventThrottle={16} > <Text> Be like water my friend … </Text> </ScrollView>

Y el controlador de eventos:

handleScroll: function(event: Object) { console.log(event.nativeEvent.contentOffset.y); },

Tenga en cuenta que puede encontrarse con problemas de rendimiento. Ajuste el acelerador en consecuencia. 16 te da la mayoría de las actualizaciones. 0 solo uno.


Para obtener la x / y después de que el desplazamiento finalizara como lo solicitaban las preguntas originales, la forma más fácil es probablemente esta:

<ScrollView horizontal={true} pagingEnabled={true} onMomentumScrollEnd={(event) => { // scroll animation ended console.log(e.nativeEvent.contentOffset.x); console.log(e.nativeEvent.contentOffset.y); }}> ...content </ScrollView>


Si desea obtener simplemente la posición actual (por ejemplo, cuando se presiona algún botón) en lugar de rastrearla cada vez que el usuario se desplaza, invocar un oyente onScroll causará problemas de rendimiento. Actualmente, la forma más eficaz de obtener simplemente la posición de desplazamiento actual es usar el paquete react-native-invoke . Hay un ejemplo para esto exactamente, pero el paquete hace muchas otras cosas.

Lea sobre esto aquí. https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd


Tratar.

<ScrollView onScroll={this.handleScroll} />

Y entonces:

handleScroll: function(event: Object) { console.log(event.nativeEvent.contentOffset.y); },