React Native: Make Each Child of ScrollView Full Height

4.7k Views Asked by At

I have a ScrollView which has two children, and I want each of the children to be the full height of the available space on the screen, meaning view 1 fills the whole screen, and then I scroll down to start to see part of slide 2. If I scroll all the way down, I should only see slide 2.

I can't figure out how to get this to happen. What is currently happening is that each child is filling half of the available vertical space, so I don't get any scrolling.

Any ideas how I can achieve this layout? Thanks!

Current UI: https://i.stack.imgur.com/5Fljc.png

Desired UI:

Code:

import React from "react";
import {
    StyleSheet,
    ScrollView,
    Text,
    View
} from "react-native";

const Home = () => {return (
    <ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollViewContainer}>
        <View style={styles.slide1}>
            <Text>this should be full height</Text>
        </View>
        <View style={styles.slide2}>
            <Text>this should also be full height, but only be visible once i scroll down</Text>
        </View>
    </ScrollView>
)};

const styles = StyleSheet.create({
    slide1: {
        justifyContent: "center",
        flexGrow: 1,
        backgroundColor: "blue"
    },
    slide2: {
        justifyContent: "center",
        flexGrow: 1,
        backgroundColor: "green"
    },
    scrollView: {
        flex: 1
    },
    scrollViewContainer: {
        flexGrow: 1
    }
});

export default Home;

3

There are 3 best solutions below

1
On BEST ANSWER

I'm not sure if there is a way to do what you are trying to accomplish with flex layout.

I would suggest getting the height of the visible container - either the height of the window or calculate it some other way, possibly using onLayout of the containing view and getting the height there, and then you have to set the height of your two inner views using that. You may need to wrap your scrollView in a View and use its onLayout function instead of the one for the scrollView.

To do the second part of your question, scrollView has a snapToInterval prop you can set.

Let me know how that goes for you or if you need code examples.

0
On

You can use react-native-swiper to achieve this functionality. Set your data or component in swiper slides and set props horizontal={false} to get vertical sliding.

So, first install react-native-swiper using this command:

npm i react-native-swiper --save

Now, import and use it as following :

import React from "react";
import { StyleSheet, ScrollView, Text, View } from "react-native";
import Swiper from "react-native-swiper";
const { width } = Dimensions.get("window");
const { height } = Dimensions.get("window");

const Home = () => {
  return (
    <Swiper style={{}} height={height} horizontal={false}>
      <View style={styles.slide1}>
        <Text>this should be full height</Text>
      </View>
      <View style={styles.slide2}>
        <Text>
          this should also be full height, but only be visible once i scroll
          down
        </Text>
      </View>
    </Swiper>
  );
};

const styles = StyleSheet.create({
  slide1: {
    justifyContent: "center",
    flexGrow: 1,
    backgroundColor: "blue",
  },
  slide2: {
    justifyContent: "center",
    flexGrow: 1,
    backgroundColor: "green",
  },
  scrollView: {
    flex: 1,
  },
  scrollViewContainer: {
    flexGrow: 1,
  },
});

export default Home;

I know this may not perfect solution, but it work around. Swiper originally made up with scrollview, so there may be not problem.

1
On

I was able to get this to work by using onLayout() as Doug Watkins suggested and updating the height of the children to match the height of the parent ScrollView:

import React, { Component } from "react";
import {
    StyleSheet,
    ScrollView,
    Text,
    View,
    LayoutChangeEvent
} from "react-native";

class Home extends Component {
    state = {
        slideHeight: 0
    };

    updateHeight = (e: LayoutChangeEvent) => {
        this.setState({ slideHeight: e.nativeEvent.layout.height });
    };

    styles = StyleSheet.create({
        slide1: {
            justifyContent: "center",
            backgroundColor: "blue"
        },
        slide2: {
            justifyContent: "center",
            backgroundColor: "green"
        },
        scrollView: {
            flex: 1
        },
        scrollViewContainer: {
            flexGrow: 1
        }
    });

    render () {
        return (
            <ScrollView style={this.styles.scrollView} contentContainerStyle={this.styles.scrollViewContainer} onLayout={this.updateHeight}>
                <View style={[this.styles.slide1, {height: this.state.slideHeight}]}>
                    <Text>this should be full height</Text>
                </View>
                <View style={[this.styles.slide2, {height: this.state.slideHeight}]}>
                    <Text>this should also be full height, but only be visible once i scroll down</Text>
                </View>
            </ScrollView>
        )
    }
};

export default Home;