É possível obter a posição de rolagem atual ou a página atual de um <ScrollView>
componente no React Native?
Então, 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
Cantou
fonte
fonte
Respostas:
Experimentar.
E depois:
fonte
event.nativeEvent.contentOffset.x
se você tiver um ScrollView horizontal;) Obrigado!scrollEventThrottle
como 16 ou menos (para obter um evento para cada quadro), não há garantia de que isso relatará o deslocamento no quadro final - o que significa que, para ter certeza de que você tem o deslocamento correto após o término da rolagem, você precisa definirscrollEventThrottle={16}
e aceitar o impacto disso no desempenho.event.nativeEvent.contentOffset.y
?Isenção de responsabilidade: o que se segue é principalmente o resultado de minhas próprias experiências no React Native 0.50. A
ScrollView
documentação está faltando muitas das informações cobertas abaixo; por exemplo,onScrollEndDrag
é completamente indocumentado. Como tudo aqui depende de comportamento não documentado, infelizmente não posso prometer que essa informação permanecerá correta daqui a um ano ou até um mês.Além disso, tudo a seguir assume uma visualização de rolagem puramente vertical, em cujo deslocamento y estamos interessados; traduzir para x offsets, se necessário, é um exercício fácil para o leitor.
Vários manipuladores de eventos em um
ScrollView
assumir umevent
e deixá-lo começar a posição de rolagem atual viaevent.nativeEvent.contentOffset.y
. Alguns desses manipuladores têm um comportamento ligeiramente diferente entre Android e iOS, conforme detalhado abaixo.onScroll
No Android
Dispara cada quadro enquanto o usuário está rolando, em cada quadro enquanto a visualização de rolagem está deslizando depois que o usuário a libera, no quadro final quando a visualização de rolagem pára e também sempre que o deslocamento da visualização de rolagem muda como resultado de seu quadro mudança (por exemplo, devido à rotação de paisagem para retrato).
No iOS
Dispara enquanto o usuário está arrastando ou enquanto a visualização de rolagem está deslizando, em alguma frequência determinada por
scrollEventThrottle
e no máximo uma vez por quadro quandoscrollEventThrottle={16}
. Se o usuário liberar a visualização de rolagem enquanto ela tem impulso suficiente para deslizar, oonScroll
manipulador também disparará quando chegar ao repouso após deslizar. No entanto, se o usuário arrasta e, em seguida, libera a exibição de rolagem enquanto ele está parado,onScroll
é não garantido para o fogo para a posição final, a menos quescrollEventThrottle
tenha sido definida de tal forma queonScroll
incêndios cada quadro de rolagem.Há um custo de desempenho na configuração
scrollEventThrottle={16}
que pode ser reduzido configurando-o para um número maior. No entanto, isso significa queonScroll
não disparará todos os quadros.onMomentumScrollEnd
Dispara quando a visualização de rolagem para após deslizar. Não dispara se o usuário liberar a visualização de rolagem enquanto ela estiver parada de forma que não deslize.
onScrollEndDrag
Dispara quando o usuário para de arrastar a visualização de rolagem - independentemente de a visualização de rolagem ficar parada ou começar a deslizar.
Dadas essas diferenças de comportamento, a melhor maneira de controlar o deslocamento depende de suas circunstâncias precisas. No caso mais complicado (você precisa suportar Android e iOS, incluindo manipulação de mudanças no
ScrollView
quadro de devido à rotação, e você não quer aceitar a penalidade de desempenho no Android da configuraçãoscrollEventThrottle
para 16), e você precisa lidar com muda para o conteúdo na visualização de rolagem também, então é uma bagunça certa.O caso mais simples é se você só precisa lidar com o Android; apenas use
onScroll
:Para oferecer suporte adicional ao iOS, se você estiver feliz em disparar o
onScroll
manipulador em todos os quadros e aceitar as implicações de desempenho disso, e se não precisar lidar com mudanças de quadro, então é apenas um pouco mais complicado:Para reduzir a sobrecarga de desempenho no iOS e, ao mesmo tempo, garantir que registremos qualquer posição em que a visualização de rolagem se estabelece, podemos aumentar
scrollEventThrottle
e fornecer adicionalmente umonScrollEndDrag
manipulador:Mas se quisermos lidar com mudanças de quadro (por exemplo, porque permitimos que o dispositivo seja girado, mudando a altura disponível para o quadro da visualização de rolagem) e / ou mudanças de conteúdo, devemos implementar adicionalmente ambos
onContentSizeChange
eonLayout
manter o controle da altura de ambos o quadro da visualização de rolagem e seu conteúdo e, assim, calcular continuamente o deslocamento máximo possível e inferir quando o deslocamento foi reduzido automaticamente devido a uma alteração no tamanho do quadro ou do conteúdo:Sim, é horrível. Também não estou 100% certo de que sempre funcionará bem nos casos em que você alterar simultaneamente o tamanho do quadro e o conteúdo da visualização de rolagem. Mas é o melhor que posso inventar e, até que esse recurso seja adicionado ao próprio framework , acho que é o melhor que alguém pode fazer.
fonte
A resposta de Brad Oyler está correta. Mas você receberá apenas um evento. Se você precisa obter atualizações constantes da posição de rolagem, você deve definir o
scrollEventThrottle
suporte, assim:E o manipulador de eventos:
Esteja ciente de que você pode ter problemas de desempenho. Ajuste o acelerador de acordo. 16 oferece mais atualizações. 0 apenas um.
fonte
function(event) { }
.scrollEventThrottle={16}
se não lhe dar "menos" atualizações; qualquer número no intervalo de 1 a 16 fornece a taxa máxima possível de atualizações. O padrão de 0 oferece a você (no iOS) um evento quando o usuário começa a rolar a tela e nenhuma atualização subsequente (o que é bastante inútil e possivelmente um bug); o padrão não é "uma vez por quadro". Além desses dois erros em seu comentário, suas outras afirmações não contradizem nada do que a resposta diz (embora você pareça pensar que sim).Se você deseja simplesmente obter a posição atual (por exemplo, quando algum botão é pressionado) em vez de rastreá-la sempre que o usuário rolar a tela, invocar um
onScroll
ouvinte causará problemas de desempenho. Atualmente, a maneira com melhor desempenho de simplesmente obter a posição de rolagem atual é usando o pacote react-native-invoke . Existe um exemplo para isso exatamente, mas o pacote faz várias outras coisas.Leia sobre isso aqui. https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd
fonte
Para obter x / y depois que a rolagem terminou como as perguntas originais solicitavam, a maneira mais fácil é provavelmente esta:
fonte
onMomentumScrollEnd
só é acionado se a visualização de rolagem tiver algum impulso quando o usuário a soltar. Se eles se soltarem enquanto a visualização de rolagem não estiver se movendo, você nunca obterá nenhum dos eventos de momentum.As respostas acima informam como obter a posição usando diferentes APIs
onScroll
,onMomentumScrollEnd
etc; Se você quiser saber o índice da página, pode calculá-lo usando o valor de deslocamento.No iOS, a relação entre ScrollView e a região visível é a seguinte:
ref: https://www.objc.io/issues/3-views/scroll-view/
fonte
Foi assim que acabou obtendo a posição de rolagem atual ao vivo da visualização. Tudo o que estou fazendo é usar o ouvinte de evento on scroll e o scrollEventThrottle. Em seguida, estou passando-o como um evento para lidar com a função de rolagem que fiz e atualizando meus adereços.
fonte
o uso de onScroll entra em um loop infinito. onMomentumScrollEnd ou onScrollEndDrag pode ser usado no lugar
fonte
Quanto à página, estou trabalhando em um componente de ordem superior que usa basicamente os métodos acima para fazer exatamente isso. Na verdade, leva um pouco de tempo quando você chega às sutilezas, como layout inicial e alterações de conteúdo. Não alegarei ter feito isso 'corretamente', mas de certa forma consideraria a resposta correta usar um componente que faça isso de forma cuidadosa e consistente.
Veja: react-native-paged-scroll-view . Adoraria receber feedback, mesmo que eu tenha feito tudo errado!
fonte
Acredito
contentOffset
que dará a você um objeto contendo o deslocamento de rolagem superior esquerdo:http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
fonte