Danny
Danny

Reputation: 871

ScrollView with flex 1 makes it un-scrollable

I'm trying to run flex on a ScrollView, and as long as the ScrollView has flex: 1 the scroll inside does not work. here is the expo fiddle (that you can run this code and play with) https://snack.expo.io/SySerKNp-

note that if you remove the flex: 1 from the ScrollView it does let scroll but then you lose the flex power ( the ability to let the red container down to push up the upper box (the ScrollView) ) so I must have a flex there.

p.s - I'm working only on android, and I haven't tested it on iPhone( I don't mind the result there )

any idea what am I missing ? why the ScrollView won't function right when it has a flex: 1 ? thanks !

Upvotes: 43

Views: 45785

Answers (6)

user14539562
user14539562

Reputation: 124

flex:1 equals to flexGrow:1 flexShrink:1 flexBasis:0;

flexGrow:1 equals to flexGrow:1 flexShrink:0 (default value) flexBasis:0.

So setting flex:1 makes ScrollView content shrink to its parent and so unscrollable.

Upvotes: 0

Sabba Keynejad
Sabba Keynejad

Reputation: 8591

The best thing to do is to wrap your ScrollView in a View and control that view with flex, your scroll view will follow.

This is a little example

<View style={{flex: 1, flexDirection: 'column',}}>

          <View style={{flex:5, backgroundColor : 'green' }}>
            <ScrollView style={{margin:50, backgroundColor : 'pink' }}>

              <Text> Hello Scroll View </Text>
              <Text> Hello Scroll View </Text>
              <Text> Hello Scroll View </Text>
              <Text> Hello Scroll View </Text>
              <Text> Hello Scroll View </Text>
              <Text> Hello Scroll View </Text>

            </ScrollView>
          </View>

          <View style={{flex:1, backgroundColor : 'blue' }}>
              <Text> Hello Static View </Text>
          </View>

</View>

Upvotes: 5

user3809729
user3809729

Reputation: 21

Try this one it will 100% solve your problem

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

export default class AlignItemsBasics extends Component {
  render() {
    return (
      // Try setting `alignItems` to 'flex-start'
      // Try setting `justifyContent` to `flex-end`.
      // Try setting `flexDirection` to `row`.
      <View style={{ flex: 1,flexDirection: 'column' }}>
        <View style={{   height: 50, backgroundColor: 'powderblue'}} />
        <View style={{  flex: 1,  backgroundColor: 'skyblue'}} >
            <ScrollView>

<View style={{  flexDirection: 'column' , minHeight: 'fit-content'}} >
 <View style={{    height:150, backgroundColor: 'red'}} />
    <View style={{ minHeight: 'fit-content', backgroundColor: '#fe3222' }} />      

 <View style={{    height:150, backgroundColor: '#fff222'}} />
    <View style={{    height:150, backgroundColor: '#555222'}} />           
              </View>

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

// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics);

Upvotes: 1

Ankit Aggarwal
Ankit Aggarwal

Reputation: 3131

Try using flexGrow: 1 instead of flex: 1 in scrollView content container style as follows.

<ScrollView contentContainerStyle={{ flexGrow: 1, borderColor: 'green', borderWidth: 5 }}>
  <View style={styles.box1} />
  <View style={styles.box2} />
  <View style={styles.box1} />
</ScrollView>

https://snack.expo.io/HkkEVoh6Z

Upvotes: 134

Shovon
Shovon

Reputation: 71

This answer has already been provided how to do it.

But here's an explanation why you cannot do by your method. The styles given in contentContainerStyle is

applied to the scroll view content container which wraps all of the child views.

So when you apply flex: 1 to contentContainer it takes full height of ScrollView whose height is also flex: 1 as its parent View.

You can also simulate -

the ability to let the red container down to push up the upper box

by adding a parent to ScrollView and apply style in the parent

<View style={styles.root}>
  <View style={{ flex: 1, borderColor: 'green', borderWidth: 5 }}>
    <ScrollView>
      <View style={styles.box1} />
      <View style={styles.box2} />
      <View style={styles.box1} />
    </ScrollView>
  </View>
  <View style={{ height: this.state.height, backgroundColor: 'red' }}>
    <TouchableOpacity onPress={() => this.setState({ height: this.state.height + 10 })}>
      <Text>Click</Text>
    </TouchableOpacity>
  </View>
</View>

Upvotes: 4

sebastianf182
sebastianf182

Reputation: 9978

I believe your problem is that you are telling the ScrollView to occupy all available space with flex=1 but the thing is that ScrollView works differently. It automatically renders all its children so it does work different with flex. That is the difference against a normal ListView or FlatList which have better performance.

I believe this snack solves that issue: https://snack.expo.io/SkxN9GOT-

Basically, I am getting the height of the device and setting the ScrollView with a fixed height, based on (screenHeight - the current height of the red box).

Upvotes: 15

Related Questions