면책 조항 : 다음은 주로 React Native 0.50에서 직접 실험 한 결과입니다. ScrollView
문서는 현재 아래에 적용되는 많은 정보가 누락; 예를 들어onScrollEndDrag
완전히 문서화되지 않았습니다. 여기에있는 모든 것은 문서화되지 않은 행동에 의존하기 때문에 안타깝게도이 정보가 지금부터 1 년 또는 심지어 한 달 후에도 정확할 것이라고 약속 할 수 없습니다.
또한 아래의 모든 것은 y 오프셋에 관심이 있는 순전히 수직 스크롤 뷰를 가정합니다 . 필요한 경우 x 오프셋으로 변환하는 것은 독자에게 쉬운 연습이되기를 바랍니다.
ScrollView
테이크 에 대한 다양한 이벤트 핸들러를 사용하면 을 event
통해 현재 스크롤 위치를 가져올 수 있습니다 event.nativeEvent.contentOffset.y
. 이러한 핸들러 중 일부는 아래에 설명 된대로 Android와 iOS간에 약간 다른 동작을합니다.
Android에서
사용자가 스크롤하는 동안 모든 프레임, 사용자가 놓은 후 스크롤 뷰가 글라이딩하는 동안 모든 프레임, 스크롤 뷰가 정지 될 때 마지막 프레임에서, 그리고 프레임의 결과로 스크롤 뷰의 오프셋이 변경 될 때마다 발생합니다. 변경 (예 : 가로에서 세로로의 회전으로 인해).
iOS에서
화재는 사용자가 드래그하거나 스크롤보기 글라이딩 동안 몇몇 주파수에 의해 결정되는 반면 scrollEventThrottle
때 프레임 당 많아야 한 번 scrollEventThrottle={16}
. 경우 사용자가 스크롤 뷰를 해제 해 글라이드에 충분한 힘을 가지고 동안 onScroll
핸들러는 화재 때 글라이딩 후 휴식을 제공합니다. 사용자가 드래그 한 후이 정지 상태에서 스크롤 뷰를 해제하는 경우에는, onScroll
되어 있지 않는 한 최종 위치에 대한 화재 보장 scrollEventThrottle
같은 설정되었는지 onScroll
화재 스크롤의 모든 프레임.
scrollEventThrottle={16}
더 큰 숫자로 설정하여 줄일 수있는 설정 성능 비용 이 있습니다. 그러나 이것은 onScroll
모든 프레임을 발사하지는 않는다는 것을 의미합니다 .
글라이딩 후 스크롤 뷰가 멈출 때 발생합니다. 사용자가 움직이지 않도록 고정되어있는 동안 스크롤 뷰를 놓으면 전혀 실행되지 않습니다.
onScrollEndDrag
사용자가 스크롤보기가 정지 된 상태로 있거나 글라이딩을 시작하는지 여부에 관계없이 스크롤보기 드래그를 중지하면 실행됩니다.
이러한 동작 차이를 고려할 때 오프셋을 추적하는 가장 좋은 방법은 정확한 상황에 따라 다릅니다. 가장 복잡한 경우 ( ScrollView
회전으로 인한의 프레임 변경 처리를 포함하여 Android 및 iOS를 지원해야하며 Android에서 설정 scrollEventThrottle
에서 16으로 의 성능 저하를 받아들이고 싶지 않음 ) 처리해야합니다. 스크롤 뷰 의 내용도 변경되면 엉망입니다.
가장 간단한 경우는 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}
>
우리가 (우리가 스크롤 뷰의 프레임에 사용 가능한 높이를 변경, 장치가 회전 할 수 있기 때문에 예를) 및 / 또는 내용 변경 프레임 변경을 처리하는 경우에, 우리는 또한 모두를 구현해야 onContentSizeChange
하고 onLayout
모두의 높이를 추적하는 스크롤 뷰의 프레임과 그 내용을 확인하여 가능한 최대 오프셋 을 지속적으로 계산하고 프레임 또는 내용 크기 변경으로 인해 오프셋이 자동으로 감소한시기를 추론합니다.
<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}
>
네, 꽤 끔찍합니다. 또한 스크롤 뷰의 프레임과 내용의 크기 를 동시에 변경하는 경우 항상 올바르게 작동 할 것이라고 100 % 확신하지는 않습니다 . 하지만 이것이 제가 생각할 수있는 최선의 방법이며, 이 기능이 프레임 워크 자체에 추가 될 때까지 누구나 할 수있는 최선이라고 생각합니다.