Search code examples
reactjsreact-nativepaginationscrollview

Scroll to a position and set left & right arrow in react native


I have following numbered pages, when user on a page, initial pagination number must be the user current page number. i have used

    <ScrollView ref={(view) => this._scrollView = view}>
    <View style={somestyle}><Text>1</Text></View>
    <View style={somestyle}><Text>2</Text></View>
     .
     .
     .
     .
    <View style={somestyle}><Text>9</Text></View>
    </ScrollView>
:
:
    this.refs._scrollView.scrollTo({x: 5, y: 0, animated: true})

(for 5th page) but not worked. Second question is how to add left< and right > arrow in scrollview Scroll view image


Solution

  • Here I have created you an example of how to add pagination with arrows to ScrollView, It can be simplified and modified.

    I did not add arrows but for simplification purposes, I use text instead like this <Text> Left Arrow </Text> . You add arrows using Icon or Image instead of Text.

    Regarding your question :

    initial pagination number must be the user current page number

    You can get the current xOffset by using this.state.currentXOffset which was set in the <ScrollView onScroll={this._handleScroll} > and setting it in the _handleScroll function. You can do your conditional for current page number there if you like.

    Full code below, you can copy and paste the component as it only handles pagination, then modify what you want.

    import React, { Component } from 'react';
    import {View, Text, StyleSheet, ScrollView, TouchableHighlight} from 'react-native';    
    
    export default class ForTest extends Component {
      constructor(props){
        super(props);
        this.state = {
          scrollViewWidth:0,
          currentXOffset:0
        }
      }
    
      _handleScroll = (event) => {
        console.log('currentXOffset =', event.nativeEvent.contentOffset.x);
        newXOffset = event.nativeEvent.contentOffset.x
        this.setState({currentXOffset:newXOffset})
      }
    
      leftArrow = () => {
        eachItemOffset = this.state.scrollViewWidth / 10; // Divide by 10 because I have 10 <View> items
        _currentXOffset =  this.state.currentXOffset - eachItemOffset;
        this.refs.scrollView.scrollTo({x: _currentXOffset, y: 0, animated: true})
      }
    
      rightArrow = () => {
        eachItemOffset = this.state.scrollViewWidth / 10; // Divide by 10 because I have 10 <View> items 
        _currentXOffset =  this.state.currentXOffset + eachItemOffset;
        this.refs.scrollView.scrollTo({x: _currentXOffset, y: 0, animated: true})
      }
    
      render() {
        //console.log('scrollViewWidth = ', this.state.scrollViewWidth)
        return (
          <View>
            <Text>Page Works!</Text>
    
            <View style={{flex:1, flexDirection:'row', justifyContent:'center'}}>
    
              <TouchableHighlight
                style={{alignItems: 'flex-start', paddingTop:20}}
                onPress={this.leftArrow}>
                <Text> Left Arrow </Text>
              </TouchableHighlight>
    
              <ScrollView 
                contentContainerStyle={{backgroundColor:'yellow', alignItems: 'center'}}
                horizontal={true}
                pagingEnabled={true}
                ref="scrollView"
                onContentSizeChange={(w, h) => this.setState({scrollViewWidth:w})}
                scrollEventThrottle={16}
                scrollEnabled={false} // remove if you want user to swipe
                onScroll={this._handleScroll}
              >
                <View style={styles.somestyle}><Text>1</Text></View>
                <View style={styles.somestyle}><Text>2</Text></View>
                <View style={styles.somestyle}><Text>3</Text></View>
                <View style={styles.somestyle}><Text>4</Text></View>
                <View style={styles.somestyle}><Text>5</Text></View>
                <View style={styles.somestyle}><Text>6</Text></View>
                <View style={styles.somestyle}><Text>7</Text></View>
                <View style={styles.somestyle}><Text>8</Text></View>
                <View style={styles.somestyle}><Text>9</Text></View>
                <View style={styles.somestyle}><Text>10</Text></View>
              </ScrollView>
    
              <TouchableHighlight
                style={{alignItems: 'flex-end', paddingTop:20}}
                onPress={this.rightArrow}>
                <Text> Right Arrow </Text>
              </TouchableHighlight>
    
            </View>
    
          </View>
        )
      }
    }
    
    const styles = StyleSheet.create({
      somestyle: {
        paddingVertical:10,
        paddingHorizontal:20,
        margin:10,
        borderWidth:1,
        borderRadius:1,
        borderColor:'black'
      }
    })
    

    I hope this helps.

    NOTE: Im not quite sure this is what you should use for your application. I think you are looking to use something like FlatLists (which inherit from VirtualizedList) instead of ScrollViews. VirtualizedList has a scrollToIndex function which is much more perceptive. Whereas, ScrollView's scrollTo expects x and y parameters meaning that you would have to calculate the exact spot to scroll to - which I had shown in the code example above(with padding style its even more complicated).