17

Is there a way in React Native to sync two or more scrollviews so they follow each other? I've seen some implementations for objective-c but have no idea how to implement that for react native.

FreeJ
  • 266
  • 1
  • 3
  • 7
  • In case someone is still looking for an answer, here is a possible implementation: https://gist.github.com/jevakallio/e95b8ee3c649eb64b2dc768be9375e11 – Moinul Hossain May 08 '17 at 21:56

5 Answers5

7

So far the cleanest and less problematic I found was this:

import React, { Component } from 'react'
import { Text, View, ScrollView } from 'react-native'

function Squares(props) {
    var squares = []
    for (var i = 0; i < props.numRows; i++) {
        squares.push(<View style={{ height: 50, backgroundColor: props.color1 }}><Text>{i}</Text></View>)
        squares.push(<View style={{ height: 50, backgroundColor: props.color2 }}><Text>{i}</Text></View>)
    }
    return squares
}

export default class App extends Component {
    constructor(props) {
        super(props)
        this.leftIsScrolling = false
        this.rigthIsScrolling = false
    }
    render() {
        return (
            <View
                style={{ flex: 1, alignItems: 'flex-start', backgroundColor: 'yellow' }}>
                <View style={{ backgroundColor: '#bbb', flexDirection: 'row' }}>

                    <ScrollView
                        scrollEventThrottle={16}
                        ref={scrollView => { this._leftView = scrollView }}
                        onScroll={e => {
                            if (!this.leftIsScrolling) {
                                this.rigthIsScrolling = true
                                var scrollY = e.nativeEvent.contentOffset.y
                                this._rightView.scrollTo({ y: scrollY })
                            }
                            this.leftIsScrolling = false
                        }}>
                        <Squares numRows={20} color1={"green"} color2={"darkgreen"} />
                    </ScrollView>

                    <ScrollView
                        ref={scrollView => { this._rightView = scrollView }}
                        scrollEventThrottle={16}
                        onScroll={e => {
                            if (!this.rigthIsScrolling) {
                                this.leftIsScrolling = true
                                var scrollY = e.nativeEvent.contentOffset.y
                                this._leftView.scrollTo({ y: scrollY })
                            }
                            this.rigthIsScrolling = false
                        }}>
                        <Squares numRows={20} color1={"red"} color2={"darkred"} />

                    </ScrollView>
                </View>
            </View>
        )
    }
}

I have also tried something along the lines of this gist but it behaves strangely due to the listener in the scroll position is always affecting the two ScrollViews.

For this I was inspired by this answer on how to do it in javascript.

dgellow
  • 692
  • 1
  • 11
  • 18
rsilva4
  • 1,915
  • 1
  • 23
  • 39
  • 1
    will lead to strange "bounce" on ios. Since `scrollTo` is not a sync move on ios, but set `this.leftIsScrolling = false;` is a sync move. – Halt May 30 '18 at 02:52
2
  1. Get the scroll position when one of them is scrolled based on this answer
  2. Set the scroll position on the other one with ScrollView.scrollTo
Community
  • 1
  • 1
Milan Gulyas
  • 632
  • 8
  • 18
0

Use refs:

let firstRef: ScrollView | null;
let secondRef: ScrollView | null;

<ScrollView
  ref={ref => (firstRef = ref)}>
...

<ScrollView
  ref={ref => (secondRef = ref)}
  onScroll={e => {
    if(firstRef) {
      firstRef.scrollTo({
      x: e.nativeEvent.contentOffset.x,
      y: e.nativeEvent.contentOffset.y,
      animated: false
      });
    }
  }  
  >
...
NKurzweil
  • 3
  • 3
0
<ScrollView>
  <ScrollView nestedScrollEnabled={true}>
  </ScrollView>
</ScrollView>

video ref. from google to explain how it works

enter image description here

Deepak Singh
  • 749
  • 4
  • 16
  • Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel May 28 '22 at 09:12
0

All these answers are a bit buggy and fail to synchronize ScrollViews with different orientations or sizes / lengths. Here is a short 3 minute video I found that uses a cleaner, far more reliant approach