2

In my React Native Project, I have a screen with a ScrollView, with lots of defined areas. In the same screen, I also have a component which creates a floating view on top of the ScrollView.

In this floating box I have a button. If the user clicks this button, the main screen should scroll down to a specific component within the ScrollView. Is it possible, and how can I do it?

App.js

import * as React from 'react';
import { Text, View, StyleSheet, ScrollView, Dimensions, Pressable } from 'react-native';
import Constants from 'expo-constants';

import Guide from './components/Guide';

import { Card } from 'react-native-paper';

export default function App() {
  return (
    <>
    <ScrollView style={styles.container}>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 1</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 2</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 3</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 4</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 5</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 6</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 7</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 8</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 9</Text>
      </Card>
      <Card style={{margin:20,padding:20}}>
        <Text style={{textAlign:'center'}}>AREA 10</Text>
      </Card>
    </ScrollView>
    <Guide />
    </>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,

    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#FFC300',
    padding: 8,
  },

  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});

Below is the Guide component.

Guide.js

import * as React from 'react';
import { Text, View, StyleSheet, Image, Dimensions, Pressable } from 'react-native';

    export default function Guide() {
      return (
        <View style={styles.context}>
        <Pressable onPress={() => {
              alert('This should scroll down to Area 8');
            }}>
          <View style={styles.blockWrapper}>
            <Text style={styles.textStyle}>Scroll to Area 8</Text>
          </View>
          </Pressable>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
        context: {
        position: 'absolute',
        width: Dimensions.width,
        height: Dimensions.height,
        top: 0,
        left: 0,
        right: 0,
        bottom: 10,
        zIndex: 1000,
        justifyContent: 'flex-end',
      },
      blockWrapper: {
        width: '100%',
        padding: 0,
        backgroundColor: '#5C93D8',
        paddingHorizontal: 20,
        paddingVertical: 15,
        // marginBottom: 20,
        borderRadius: 20,
        justifyContent: 'center',
        minHeight:100
      },
    });

The button produced by Guide floats over the ScrollView. When I click that, the main screen should scroll down to Area 8. I don't know how to make this happen. I've seen some threads on using ref on scroll but couldn't find a good explanation. Can you please help?

You can see the snack for the same here: https://snack.expo.io/lRl8ffSWo . Note that in my real project, I'm not using Expo.

1 Answer 1

2

You can use ref to do that. <ScrollView ref={yourRef} ... /> and onClick you can scroll to some position. ref.current.scrollTo({ y: <offset> }) but there are better way, instead of ScrollView you can use FlatList where you can pass only index instead of offset. <FlatList ref={yourRef} ... /> and you can scroll to some index using ref.current.scrollToIndex({ index: <your_index> }).

Sign up to request clarification or add additional context in comments.

8 Comments

WIthin ScrollView itself, isn't it possible to get the offset of a rendered element (in this case Area 8) and then scroll to that? Also, I need to scroll from another component altogether. I get what you're saying, but I'm not sure how to implement it in the correct way.
snack.expo.io/UoumJa9eE I updated your snack, there is an example of how to scroll to the 4th card, I passed 300 (offset from top) because every card has about 50 height and space between them is 40.. so 3x50 + 3x40 and + 20 (space above the first card).
@asanas Ok, if you want to scroll from another component, you need to pass the desired index as a prop, 8 in your case and calculate an offset. Let's say that every card is 50 height and you need to hide 7 because 8th must be on the top, you can use formula: const offset = (desiredIndex - 1) * 50 + (desiredIndex - 1) * 40;
Thanks. I can pass the index. But how do I pass the ref to another component, and how do I call the ref.current.scrollTo() from that other component. Could you please help me with it? I have the Guide component. If you could show me how to make it work with that component...
@asanas I'm glad to help you. When you want to pass ref as a prop to other components, you need to use forwardRef. Check the doc
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.