React Native에서 ScrollView의 현재 스크롤 위치 가져 오기
<ScrollView>
React Native에서 현재 스크롤 위치 또는 구성 요소 의 현재 페이지를 가져올 수 있습니까?
그래서 다음과 같습니다.
<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>
시험.
<ScrollView onScroll={this.handleScroll} />
그리고:
handleScroll: function(event: Object) {
console.log(event.nativeEvent.contentOffset.y);
},
면책 조항 : 다음은 주로 React Native 0.50에서 직접 실험 한 결과입니다. ScrollView
문서는 현재 아래에 적용되는 많은 정보가 누락; 예를 들어 onScrollEndDrag
완전히 문서화되지 않았습니다. 여기에있는 모든 것은 문서화되지 않은 행동에 의존하기 때문에 안타깝게도이 정보가 지금부터 1 년 또는 심지어 한 달 후에도 정확한 상태로 유지 될 것이라고 약속 할 수 없습니다.
또한 아래의 모든 것은 y 오프셋에 관심이 있는 순전히 수직 스크롤 뷰를 가정합니다 . 필요한 경우 x 오프셋으로 변환하는 것은 독자에게 쉬운 연습이되기를 바랍니다.
ScrollView
테이크 에 대한 다양한 이벤트 핸들러를 사용하면 을 event
통해 현재 스크롤 위치를 가져올 수 있습니다 event.nativeEvent.contentOffset.y
. 이러한 핸들러 중 일부는 아래에 설명 된대로 Android와 iOS간에 약간 다른 동작을합니다.
onScroll
Android에서
사용자가 스크롤하는 동안 모든 프레임, 사용자가 놓은 후 스크롤 뷰가 글라이딩하는 동안 모든 프레임, 스크롤 뷰가 정지 될 때 마지막 프레임에서, 그리고 프레임의 결과로 스크롤 뷰의 오프셋이 변경 될 때마다 발생합니다. 변경 (예 : 가로에서 세로로의 회전으로 인해).
iOS에서
화재는 사용자가 드래그하거나 스크롤보기 글라이딩 동안 몇몇 주파수에 의해 결정되는 반면 scrollEventThrottle
때 프레임 당 많아야 한 번 scrollEventThrottle={16}
. 경우 사용자가 스크롤 뷰를 해제 해 글라이드에 충분한 힘을 가지고 동안 onScroll
핸들러는 화재 때 글라이딩 후 휴식을 제공합니다. 사용자가 드래그 한 후이 정지 상태에서 스크롤 뷰를 해제하는 경우에는, onScroll
되어 있지 않는 한 최종 위치에 대한 화재 보장 scrollEventThrottle
같은 설정되었는지 onScroll
화재 스크롤의 모든 프레임.
scrollEventThrottle={16}
더 큰 숫자로 설정하여 줄일 수있는 설정 성능 비용 이 있습니다. 그러나 이것은 onScroll
모든 프레임을 발사하지는 않는다는 것을 의미합니다 .
onMomentumScrollEnd
글라이딩 후 스크롤 뷰가 멈출 때 발생합니다. 사용자가 움직이지 않도록 고정되어있는 동안 스크롤 뷰를 놓으면 전혀 실행되지 않습니다.
onScrollEndDrag
사용자가 스크롤보기가 정지 된 상태로 있거나 글라이딩을 시작하는지 여부에 관계없이 스크롤보기 드래그를 중지하면 실행됩니다.
이러한 동작 차이를 고려할 때 오프셋을 추적하는 가장 좋은 방법은 정확한 상황에 따라 다릅니다. 가장 복잡한 경우 ( ScrollView
회전으로 인한의 프레임 변경 처리를 포함하여 Android 및 iOS를 지원해야하며 설정 scrollEventThrottle
에서 16 까지의 Android에서 성능 저하를 받아들이고 싶지 않음 ) 처리해야합니다. 스크롤 뷰 의 내용도 변경되면 엉망입니다.
가장 간단한 경우는 Android 만 처리해야하는 경우입니다. 그냥 사용하십시오 onScroll
:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
>
또한 아이폰 OS를 지원하기 위해, 만약 당신이하고있는 화재 행복 onScroll
핸들러마다 프레임을 그의 성능에 영향을 동의 한 경우에 당신이 핸들 프레임 변경이 필요하지 않습니다, 그것은 조금 더 복잡 비트 전용입니다 :
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
scrollEventThrottle={16}
>
iOS에서 성능 오버 헤드를 줄이면서 스크롤 뷰가 고정되는 위치를 기록하도록 보장 scrollEventThrottle
하기 위해 onScrollEndDrag
핸들러를 늘리고 추가로 제공 할 수 있습니다 .
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
onScrollEndDrag={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
scrollEventThrottle={160}
>
But if we want to handle frame changes (e.g. because we allow the device to be rotated, changing the available height for the scroll view's frame) and/or content changes, then we must additionally implement both onContentSizeChange
and onLayout
to keep track of the height of both the scroll view's frame and its contents, and thereby continually calculate the maximum possible offset and infer when the offset has been automatically reduced due to a frame or content size change:
<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}
>
Yeah, it's pretty horrifying. I'm also not 100% certain that it'll always work right in cases where you simultaneously change the size of both the frame and content of the scroll view. But it's the best I can come up with, and until this feature gets added within the framework itself, I think this is the best that anyone can do.
Brad Oyler's answer is correct. But you will only receive one event. If you need to get constant updates of the scroll position, you should set the scrollEventThrottle
prop, like so:
<ScrollView onScroll={this.handleScroll} scrollEventThrottle={16} >
<Text>
Be like water my friend …
</Text>
</ScrollView>
And the event handler:
handleScroll: function(event: Object) {
console.log(event.nativeEvent.contentOffset.y);
},
Be aware that you might run into performance issues. Adjust the throttle accordingly. 16 gives you the most updates. 0 only one.
If you wish to simply get the current position (e.g. when some button is pressed) rather than tracking it whenever the user scrolls, then invoking an onScroll
listener is going to cause performance issues. Currently the most performant way to simply get current scroll position is using react-native-invoke package. There is an example for this exact thing, but the package does multiple other things.
Read about it here. https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd
To get the x/y after scroll ended as the original questions was requesting, the easiest way is probably this:
<ScrollView
horizontal={true}
pagingEnabled={true}
onMomentumScrollEnd={(event) => {
// scroll animation ended
console.log(e.nativeEvent.contentOffset.x);
console.log(e.nativeEvent.contentOffset.y);
}}>
...content
</ScrollView>
As for the page, I'm working on a higher order component that uses basically the above methods to do exactly this. It actually takes just a bit of time when you get down to the subtleties like initial layout and content changes. I won't claim to have done it 'correctly', but in some sense I'd consider the correct answer to use component that does this carefully and consistently.
See: react-native-paged-scroll-view. Would love feedback, even if it's that I've done it all wrong!
This is how ended up getting the current scroll position live from the view. All I am doing is using the on scroll event listener and the scrollEventThrottle. I am then passing it as an event to handle scroll function I made and updating my props.
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} />
)
}
}
I believe contentOffset
will give you an object containing the top-left scroll offset:
http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
'development' 카테고리의 다른 글
80 이외의 포트에서 수신하도록 Apache 구성 (0) | 2020.08.29 |
---|---|
새로운 computeIfAbsent 함수를 어떻게 사용합니까? (0) | 2020.08.29 |
XML 렌더링 오류 Android 미리보기 N (0) | 2020.08.29 |
Android API 23 플랫폼에 대한 소스를 찾을 수 없음 (Android Studio 2.0) (0) | 2020.08.29 |
\ begin {itemize} [닫힘] 전에 공백 제거 (0) | 2020.08.29 |