I have a ScrollView with 2 subviews and I want the first of them (lets call it ViewA) to have {flex: 1} so the other one (ViewB) will stick to the bottom of the screen - but only if their total height is smaller that the screen. Of course that if they are higher than the screen I want it to scroll as usual.
Case 1 (GOOD): ViewA with long text, ViewB scrolls with it. https://rnplay.org/apps/slCivA
Case 2 (BAD): ViewA with short text, ViewB doesn't stick to the bottom. https://rnplay.org/apps/OmQakQ
So I set the ScrollView's style AND contentContainerStyle to be flex: 1. I Also set ViewA's style to flex:1. But when I do it, the ScrollView's contentContainer view is fixed to the screen height, thus not able to scroll if needed and even worse - ViewB overlaps ViewA.
Case 3 (BAD): ViewB sticks to the bottom, but the whole thing doesn't scroll. https://rnplay.org/apps/wZgtWA
If it's a bug - how to fix/workaround it? If it's the expected behaviour - how can I achieve what I've described?
Thanks.
ScrollView is a component which doesn't inherit the use of flex .
ScrollView renders all its react child components at once, but this has a performance downside. FlatList renders items lazily, when they are about to appear, and removes items that scroll way off-screen to save memory and processing time.
flexGrow describes how any space within a container should be distributed among its children along the main axis. After laying out its children, a container will distribute any remaining space according to the flex grow values specified by its children.
Try feeding {flexGrow: 1}
to the contentContainerStyle prop instead
Ok, so i wasn't able to get it work by styling alone, but here's how I did it:
onLayout
, and measure
)measure
callback, I add the height (if needed) to a spacer view between ViewA and ViewB in order to place ViewB on the bottom.my CJSX code (stripped and simplified version):
Dimensions = require('Dimensions')
windowSize = Dimensions.get('window')
MyClass = React.createClass
mixins: [TimerMixin]
render: ->
<ScrollView style={styles.container} automaticallyAdjustContentInsets={false}>
<View style={styles.mainContainer}>
... THIS IS VIEW A ...
</View>
{
if [email protected]
<View>
<ActivityIndicatorIOS/>
</View>
}
<View style={[styles.spacer, {height: @state.spacerSize || 0}]}></View>
<View onLayout={@measureFooterPosition} style={[styles.extras, {opacity: if @state.footerWasFixed then 1 else 0 }]} ref='extras'>
... THIS IS VIEW B ...
</View>
</ScrollView>
measureFooterPosition: ->
@refs.extras.measure(@fixFooterPosition)
fixFooterPosition: (ox, oy, width, height) ->
footerPosition = Math.round(oy + height)
diff = windowSize.height - footerPosition
if diff > 0
@setState(spacerSize: diff)
if [email protected]
@setTimeout (=>
@setState(footerWasFixed: true)
), 30
styles = StyleSheet.create(
container:
backgroundColor: 'grey'
flex: 1
spacer:
backgroundColor: 'white'
mainContainer:
flex: 1
backgroundColor: 'white'
extras:
backgroundColor: 'white')
It's very simplified code, (my view has requirements much more specific then this..) but I hope it helps anyone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With