現在のスクロール位置、またはReact Nativeの<ScrollView>
コンポーネントの現在のページを取得することは可能ですか?
のようなもの:
<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
documentation には、現在、以下で説明する多くの情報がありません。たとえば、onScrollEndDrag
は完全に文書化されていません。ここではすべてが文書化されていない動作に依存しているため、残念ながら、この情報が今から1年または1か月後にも正しいままであるという約束はできません。
また、以下のすべては、関心のある y オフセットを持つ純粋に垂直なスクロールビューを想定しています。 x オフセットへの変換は、必要に応じて、読者にとって簡単な練習になることを願っています。
ScrollView
のさまざまなイベントハンドラーはevent
を受け取り、event.nativeEvent.contentOffset.y
を介して現在のスクロール位置を取得できます。これらのハンドラーの一部は、AndroidとiOSの間で動作がわずかに異なります(以下で詳しく説明します)。
onScroll
ユーザーがスクロールしている間、すべてのフレーム、ユーザーがリリースした後にスクロールビューが滑っている間、スクロールビューが静止する最終フレーム、およびフレームの結果としてスクロールビューのオフセットが変更されるたびに発生します。変更(例えば、横から縦への回転による)。
ユーザーがドラッグしている間、またはスクロールビューが滑っている間に、 scrollEventThrottle
で決定される一定の頻度で、scrollEventThrottle={16}
のときにフレームごとに最大1回発生します。 ユーザーがスクロールするのに十分な勢いがあるときにスクロールビューを離すと、onScroll
ハンドラーは、グライド後の静止時にも起動します。ただし、ユーザーが静止している間にスクロールビューをドラッグしてから離すと、onScroll
がすべてのフレームで起動するようにscrollEventThrottle
が設定されていない限り、onScroll
は not スクロール。
scrollEventThrottle={16}
の設定にはパフォーマンスコストがありますが、これを大きく設定することで削減できます。ただし、これはonScroll
がすべてのフレームを起動するわけではないことを意味します。
onMomentumScrollEnd
グライド後にスクロールビューが停止したときに発生します。ユーザーがスクロールしないように静止しているときにユーザーがスクロールビューを離した場合、まったく起動しません。
onScrollEndDrag
ユーザーがスクロールビューのドラッグを停止すると、スクロールビューが静止したままであるか、滑空し始めたかにかかわらず発生します。
これらの動作の違いを考えると、オフセットを追跡する最善の方法は、正確な状況に依存します。最も複雑な場合(AndroidおよびiOSをサポートする必要があります。これには、ScrollView
のフレームの回転による変更を処理する必要があり、AndroidのscrollEventThrottle
の設定によるパフォーマンスの低下を受け入れたくない場合) 16)スクロールビューで content への変更も処理する必要がある場合、それはまさに混乱です。
最も単純なケースは、Androidのみを処理する必要がある場合です。 onScroll
を使用するだけです:
<ScrollView
onScroll={event => {
this.yOffset = event.nativeEvent.contentOffset.y
}}
>
さらにiOSをサポートするには、 if フレームごとにonScroll
ハンドラーを起動し、そのパフォーマンスへの影響を受け入れて、 if youフレームの変更を処理する必要はありません、それはほんの少し複雑です:
<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
スクロールビューのフレームとそのコンテンツの両方の高さを追跡し、 maximum 可能なオフセットを継続的に計算し、オフセットがいつになるかを推測しますフレームまたはコンテンツサイズの変更により自動的に縮小されます。
<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%確実ではありません。しかし、それは私が考え出すことができる最高のものであり、 この機能はフレームワーク自体に追加されます になるまで、これは誰でもできる最高のものだと思います。
Brad Oylerの答えは正しい。ただし、受け取るイベントは1つだけです。スクロール位置の継続的な更新を取得する必要がある場合は、次のようにscrollEventThrottle
propを設定する必要があります。
<ScrollView onScroll={this.handleScroll} scrollEventThrottle={16} >
<Text>
Be like water my friend …
</Text>
</ScrollView>
そして、イベントハンドラー:
handleScroll: function(event: Object) {
console.log(event.nativeEvent.contentOffset.y);
},
パフォーマンスの問題が発生する可能性があることに注意してください。それに応じてスロットルを調整します。 16は、ほとんどの更新を提供します。 0 1つだけ。
ユーザーがスクロールするたびに追跡するのではなく、単に現在の位置を取得したい場合(ボタンが押された場合など)、onScroll
リスナーを呼び出すとパフォーマンスの問題が発生します。現在、単純に現在のスクロール位置を取得する最もパフォーマンスの高い方法は、 react-native-invoke パッケージを使用することです。この正確な例はありますが、パッケージは他にも複数のことを行います。
ここでそれについて読んでください。 https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd
元の質問が要求していたときにスクロールが終了した後にx/yを取得するには、おそらく最も簡単な方法は次のとおりです。
<ScrollView
horizontal={true}
pagingEnabled={true}
onMomentumScrollEnd={(event) => {
// scroll animation ended
console.log(e.nativeEvent.contentOffset.x);
console.log(e.nativeEvent.contentOffset.y);
}}>
...content
</ScrollView>
ページに関しては、基本的に上記のメソッドを使用して正確にこれを行う高次コンポーネントに取り組んでいます。実際には、最初のレイアウトやコンテンツの変更などの微妙な問題に取り掛かるのに少し時間がかかります。私はそれを「正しく」行ったと主張しませんが、ある意味では、これを注意深く一貫して行うコンポーネントを使用するための正しい答えを考えます。
react-native-paged-scroll-view を参照してください。たとえそれがすべて間違っていたとしても、フィードバックを歓迎します!
contentOffset
は、左上のスクロールオフセットを含むオブジェクトを提供すると信じています。
http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
これが、現在のスクロール位置をビューからライブで取得する方法です。私がしているのは、on scrollイベントリスナーとscrollEventThrottleを使用することだけです。次に、作成したスクロール機能を処理するイベントとしてそれを渡し、小道具を更新します。
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} />
)
}
}