Why does scrollview fills the gap at the bottom of the screen?

180 views Asked by At

I have been issues with the ScrollView when I combined it with SafeAreaView. It leaves some gaps at the bottom. I also tried moving ScrollView from outside of SafeAreaView (after removing flex, flexGrow from SafeAreaView), but the SafeAreaView is taking up too much space on top (see the second image). How can I let ScrollView to take whole empty space? Bear in mind that Text to explain the gap will be removed.

import React from "react";
import { ScrollView, Text, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";

const ScrollViewPage = (props) => {
  return (
    <>
      <SafeAreaView
        style={{
          backgroundColor: "#EFF0F3",
          flex: 1,
          flexGrow: 1,
          borderWidth: 3,
          borderColor: "red",
        }}
      >
        <ScrollView
          showsVerticalScrollIndicator={false}
          contentContainerStyle={{
            flexGrow: 1,
            flex: 1,
            borderWidth: 2,
            borderColor: "blue",
            height: "100%",
            width: "100%",
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          <View
            style={{
              borderWidth: 1,
              flex: 1,

              alignItems: "center",
              justifyContent: "center",
            }}
          >
            <Text>Hello</Text>
          </View>
        </ScrollView>
        <Text>Why doesn't the scrollview fill here?</Text>
      </SafeAreaView>
    </>
  );
};

Here is the screenshot of the issue

The second image:

The Second Image

4

There are 4 answers

3
Kid Yume On

To troubleshoot it imagine pure html. Your Scrollview is probably wrapped in a div of sorts. so for example

<html>
<head>
</head>
<body>
 
  <!-- ======= Header would typically go here ======= -->
  <header>
      <!-- ======= NavBar would typically go here ======= -->
      <navbar>
      </navbar>
  <header/>
  <!-- ======= Now the Content and your ScrollView would go here======= -->
  <!-- ===When React renders your code looks like this probably======= -->
  <div>
   <ScrollView>
   </ScrollView>
  </div>
  <!-- ===This is going to make your ScrollView take the shape of parent======= -->
</body>

</html>

In react when you are calling components sometimes it gets automatically wrapped and takes the size of it's parent. ScrollViewPAge would be the parent in this case. You will need to set the size of that container. Can you share what the source looks like after it renders? especially using <> as a place holder. If you try wrapping everything in a div do you get different results? I would also try absolute values for fun to see if you get closer. If you do there is a parent you have out there.

3
Waseem Kurne On
  1. Remove unnecessary properties from SafeAreaView style.
  2. Remove unnecessary properties from ScrollView contentContainerStyle.
  3. Remove the extra View that wraps the Text component.

Here is the updated code

import React from "react";
import { ScrollView, Text, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";

const ScrollViewPage = (props) => {
  return (
    <>
      <SafeAreaView
        style={{
          flex: 1,
          backgroundColor: "#EFF0F3",
        }}
      >
        <ScrollView
          showsVerticalScrollIndicator={false}
          contentContainerStyle={{
            flex: 1,
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <View
            style={{
              flex: 1,
              justifyContent: "center",
              alignItems: "center",
            }}
          >
            <Text>Hello</Text>
          </View>
        </ScrollView>
      </SafeAreaView>
    </>
  );
};

export default ScrollViewPage;
0
Shubham Kumar On

Instead of using SafeAreaView, you can use useSafeAreaInsets() from 'react-native-safe-area-context' hook to get the insets and apply the padding only on the top of your ScrollView which should solve your use case.

Here's how I did it:

import { ScrollView, Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

export const ScrollViewPage = (props) => {
  const insets = useSafeAreaInsets();

  // You can check the inset values of top,bottom, left & right here
  console.log(insets);

  return (
    <>
      <ScrollView
        showsVerticalScrollIndicator={false}
        contentContainerStyle={{
          flexGrow: 1,
          flex: 1,
          borderWidth: 2,
          borderColor: 'blue',
          height: '100%',
          width: '100%',
          alignItems: 'center',
          justifyContent: 'center',
        }}
        style={{ paddingTop: insets.top }}>
        <View
          style={{
            borderWidth: 1,
            flex: 1,

            alignItems: 'center',
            justifyContent: 'center',
          }}>
          <Text>Hello</Text>
        </View>
      </ScrollView>
      <Text>Why doesn't the scrollview fill here?</Text>
    </>
  );
};

For reference, you can check the snack here

0
Jonas Beck On

I think the reason would be missing style prop in ScrollView.

<ScrollView
 style={{flex: 1}}
 contentContainerStyle={{flexGrow: 1}}
>
 ...
</ScrollView>