免責事項:以下は主に、React Native 0.50での私自身の実験の結果です。ScrollView
ドキュメントには、現在、以下の対象と多くの情報が欠落しています。たとえばonScrollEndDrag
、完全に文書化されていません。ここにあるものはすべて、文書化されていない動作に依存しているため、残念ながら、この情報が1年後または1か月後も正しいままであることを約束することはできません。
また、以下のすべては、対象とするyオフセットを持つ純粋な垂直スクロールビューを想定しています。必要に応じて、xオフセットに変換することは、読者にとって簡単な練習になると思います。
ScrollView
テイクのさまざまなイベントハンドラーにより、を使用しevent
て現在のスクロール位置を取得できますevent.nativeEvent.contentOffset.y
。以下に詳述するように、これらのハンドラーの一部は、AndroidとiOSで動作がわずかに異なります。
Androidの場合
ユーザーがスクロールしている間すべてのフレーム、ユーザーがスクロールビューを離した後にスクロールビューが滑空している間すべてのフレーム、スクロールビューが静止した最後のフレーム、およびフレームの結果としてスクロールビューのオフセットが変更されたときに起動します。変化する(例:横から縦への回転による)。
iOSの場合
ユーザーがドラッグしているとき、またはスクロールビューがグライドしているscrollEventThrottle
ときに発生しscrollEventThrottle={16}
ます。特定の頻度で決定され、フレームごとに最大1回発生します。場合は、ユーザーがスクロールビューを解放することがグライドするのに十分な勢いを持っていながら、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
}}
>
さらに、iOSのをサポートするためにあれば発射するあなたがいる幸せ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%確実ではありません。しかし、それは私が思いつくことができる最高のものであり、この機能がフレームワーク自体に追加されるまで、これは誰でもできる最高のものだと思います。