¿Es posible obtener la posición de desplazamiento actual o la página actual de un <ScrollView>
componente 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>
ios
reactjs
react-native
Cantó
fuente
fuente
Respuestas:
Tratar.
Y entonces:
fuente
event.nativeEvent.contentOffset.x
si tiene un ScrollView horizontal;) ¡Gracias!scrollEventThrottle
16 o menos (para obtener un evento para cada fotograma), no hay garantía de que esto informe el desplazamiento en el fotograma final , lo que significa que para asegurarse de que tiene el desplazamiento correcto después de que el desplazamiento haya terminado, necesita establecerscrollEventThrottle={16}
y aceptar el impacto en el rendimiento de eso.event.nativeEvent.contentOffset.y
?Descargo de responsabilidad: lo que sigue es principalmente el resultado de mi propia experimentación en React Native 0.50. Actualmente, a la
ScrollView
documentación le falta mucha de la información que se describe a continuación; por ejemplo,onScrollEndDrag
está completamente indocumentado. Dado que todo aquí se basa en 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 asume una vista de desplazamiento puramente vertical cuyo desplazamiento y nos interesa; traducir ax compensaciones, si es necesario, es con suerte un ejercicio fácil para el lector.
Varios controladores de eventos en una
ScrollView
tomaevent
y le permiten obtener la posición de desplazamiento actual a través deevent.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 fotograma mientras el usuario se desplaza, en cada fotograma mientras la vista de desplazamiento se desliza después de que el usuario la suelta, en el fotograma final cuando la vista de desplazamiento se detiene, y también siempre que el desplazamiento de la vista de desplazamiento cambia como resultado de su fotograma cambiando (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 una frecuencia determinada por
scrollEventThrottle
y como máximo una vez por cuadro cuandoscrollEventThrottle={16}
. Si el usuario suelta la vista de desplazamiento mientras tiene suficiente impulso para planear, elonScroll
controlador también disparará cuando se detenga después de planear. Sin embargo, si el usuario arrastra y suelta el punto de vista de desplazamiento mientras está parado,onScroll
está no garantizada al fuego para la posición final a menos quescrollEventThrottle
se ha establecido de tal manera queonScroll
los incendios cada fotograma de desplazamiento.Hay un costo de rendimiento en la configuración
scrollEventThrottle={16}
que se puede reducir configurándolo en un número mayor. Sin embargo, esto significa queonScroll
no disparará todos los fotogramas.onMomentumScrollEnd
Se dispara cuando la vista de desplazamiento se detiene después de planear. No dispara en absoluto si el usuario suelta la vista de desplazamiento mientras está estacionaria para que no se deslice.
onScrollEndDrag
Se dispara 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 de la compensación depende de sus circunstancias precisas. En el caso más complicado (necesita ser compatible con Android e iOS, incluido el manejo de cambios en el
ScrollView
marco debido a la rotación, y no desea aceptar la penalización de rendimiento en Android de la configuraciónscrollEventThrottle
a 16), y debe manejar También cambia el contenido en la vista de desplazamiento, entonces es un maldito desastre.El caso más simple es si solo necesita manejar Android; solo usa
onScroll
:Para admitir adicionalmente iOS, si está contento de despedir al
onScroll
controlador en cada cuadro y acepta las implicaciones de rendimiento de eso, y si no necesita manejar los cambios de cuadro, entonces es solo un poco más complicado:Para reducir la sobrecarga de rendimiento en iOS y, al mismo tiempo, garantizar que registremos cualquier posición en la que se asiente la vista de desplazamiento, podemos aumentar
scrollEventThrottle
y, además, proporcionar unonScrollEndDrag
controlador:Pero si queremos manejar cambios de marco (por ejemplo, porque permitimos que se gire el dispositivo, cambiando la altura disponible para el marco de la vista de desplazamiento) y / o cambios de contenido, entonces debemos implementar adicionalmente tanto
onContentSizeChange
yonLayout
realizar un seguimiento de la altura de ambos el marco de la vista de desplazamiento y su contenido y, por lo tanto, calcular continuamente el desplazamiento máximo posible e inferir cuándo el desplazamiento se ha reducido automáticamente debido a un cambio de tamaño del marco o del contenido:Sí, es bastante horrible. Tampoco estoy 100% seguro de que siempre funcione bien en los casos en los 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.
fuente
La respuesta de Brad Oyler es correcta. Pero solo recibirás un evento. Si necesita obtener actualizaciones constantes de la posición de desplazamiento, debe configurar el
scrollEventThrottle
accesorio, así:Y el controlador de eventos:
Tenga en cuenta que puede tener problemas de rendimiento. Ajuste el acelerador en consecuencia. 16 te ofrece la mayor cantidad de actualizaciones. 0 solo uno.
fuente
function(event) { }
.scrollEventThrottle={16}
no le da "menos" actualizaciones; cualquier número en el rango del 1 al 16 le brinda la máxima tasa de actualizaciones posible. El valor predeterminado de 0 le brinda (en iOS) un evento cuando el usuario comienza a desplazarse y luego no hay actualizaciones posteriores (lo cual es bastante inútil y posiblemente un error); el valor predeterminado no es "una vez por cuadro". Además de esos dos errores en su comentario, sus otras afirmaciones no contradicen nada de lo que dice la respuesta (aunque parece pensar que lo hacen).Si simplemente desea obtener la posición actual (por ejemplo, cuando se presiona algún botón) en lugar de rastrearlo cada vez que el usuario se desplaza, entonces invocar a un
onScroll
oyente causará problemas de rendimiento. Actualmente, la forma más eficaz de simplemente obtener la posición de desplazamiento actual es usar react-native-invoke paquete . 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
fuente
Para obtener el x / y después de que el desplazamiento terminó como lo solicitaban las preguntas originales, la forma más fácil es probablemente esta:
fuente
onMomentumScrollEnd
solo se activa si la vista de desplazamiento tiene cierto impulso cuando el usuario la suelta. Si se sueltan mientras la vista de desplazamiento no se está moviendo, nunca obtendrá ninguno de los eventos de impulso.Las respuestas anteriores indican cómo obtener la posición utilizando diferentes API
onScroll
,onMomentumScrollEnd
etc. Si desea conocer el índice de la página, puede calcularlo utilizando el valor de compensación.En iOS, la relación entre ScrollView y la región visible es la siguiente:
ref: https://www.objc.io/issues/3-views/scroll-view/
fuente
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 de desplazamiento y scrollEventThrottle. Luego lo paso como un evento para manejar la función de desplazamiento que hice y actualizar mis accesorios.
fuente
el uso de onScroll entra en un bucle infinito. En su lugar, se puede utilizar onMomentumScrollEnd o onScrollEndDrag
fuente
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, solo lleva 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 de manera cuidadosa y consistente.
Ver: react-native-paged-scroll-view . Me encantaría recibir comentarios, ¡incluso si lo he hecho todo mal!
fuente
Yo creo
contentOffset
le dará un objeto que contiene el desplazamiento de desplazamiento superior izquierdo:http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
fuente