40

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 !

Danny
  • 793
  • 1
  • 9
  • 20
  • How to run code at _snack_? ... also not sure, though I think you needed to wrap the `ScrollView` in a `View` – Asons Oct 18 '17 at 08:04
  • Did you try adding `flex: 1` to the outer most `View`? – Asons Oct 18 '17 at 08:11
  • @LGSon yes I tried it still doesn't work right, either way I'm losing the flex or the scroll. – Danny Oct 18 '17 at 09:06
  • And when you wrapped the `ScrollView` in a `View`, note that it is the `View` that should have `flex: 1` – Asons Oct 18 '17 at 09:09
  • yeah as you can see in line 34 the root `View` has `flex: 1` – Danny Oct 18 '17 at 09:25
  • No, don't mean that, I mean to wrap the `ScrollView` in a `View` of its own, and that `View` should have `flex: 1` – Asons Oct 18 '17 at 09:28
  • and btw I have no choice but to wrap the `ScrollView` with a `View` as I have another `View` after it (the red box that supposed to push up) – Danny Oct 18 '17 at 09:28
  • 1
    Why can't you do that? ...and that might be needed to fix this, like this: https://snack.expo.io/HkNEysN6- – Asons Oct 18 '17 at 09:29
  • how come ? the return value needs to be properer JSX or you use one Component or you use a wrapper Component (In case of more - like mine .. I have a ScrollView and a View under it). – Danny Oct 18 '17 at 09:33
  • So this doesn't work? https://snack.expo.io/HkNEysN6- – Asons Oct 18 '17 at 09:35
  • @LGSon, I just tried the example you linked, as you can see you are losing the flex there (you can not see the green bottom border of the ScrollView) and red box is going over it instead of pushing it up. – Danny Oct 18 '17 at 09:35
  • No, can't see anything as I don't have a React environment to test it with, so I just apply standard Flexbox behavior to the code base – Asons Oct 18 '17 at 09:36
  • @LGSon, inside the link you have down a 'preview' option that opens an emulator, and you can play with it. – Danny Oct 18 '17 at 09:38
  • @LGSon,thanks for the reply but I don't see anything wrong with the code that I posted, I guess it's something about `ScrollView` component that I'm missing. – Danny Oct 18 '17 at 09:43
  • This border thing appears to me as an effect from not having `box-sizing: border-box`, so adding the extra `view` and set the border on it seems to work: https://snack.expo.io/r1-Ewj4Tb – Asons Oct 18 '17 at 10:05
  • @LGSon, this way the flex works on the `View`, but I'm losing the location on the current scroll in the `ScrollView` thats why I insist to make the flex on the ScrollView itself (so the ScrollView will be pushed up). as I said It's not a flex-box issue its more of react-native's ScrollView component issue. – Danny Oct 18 '17 at 10:31
  • 1
    @Danny It is because of the way that ScrollView works internally. Please explain what is it that you want to accomplish. Do you want to show a list of boxes above the red box? What is the thing that is not working right now? (Note: If I click on the red box nothing happens in the last expo) – sebastianf182 Oct 20 '17 at 16:26
  • @sfratini you have to click on the text "Click" to get the red box to grow. I believe what Danny wants is for the red box at the bottom to push up on the ScrollView, making it smaller (shorter) with each "Click" but also have the items inside scrollable. – Chris Geirman Oct 20 '17 at 20:38
  • Got it. I just posted something I believe fixes the issue. – sebastianf182 Oct 21 '17 at 00:55
  • @Danny try to change flex: 1 to flexGrow: 1 in the scrollview style. That should work I guess. – Ankit Aggarwal Oct 24 '17 at 11:27
  • @Danny did you try the above solution as it is working for me – Ankit Aggarwal Oct 25 '17 at 09:52

6 Answers6

117

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

Ankit Aggarwal
  • 2,941
  • 2
  • 17
  • 26
15

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).

sebastianf182
  • 9,844
  • 3
  • 34
  • 66
5

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>
Sabba Keynejad
  • 7,895
  • 2
  • 26
  • 22
4

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>
Shovon
  • 71
  • 3
1

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);
CodeF0x
  • 2,624
  • 6
  • 17
  • 28
0

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.

user14539562
  • 124
  • 3