0

I want to create a ScrollView that has two columns containing Views of asymmetrical heights. I do not think this is possible to do using flexbox, so I'm playing around with it using absolute values (discouraged per docs).

Target image

All subviews appear as I expect. I can scroll but when I release my finger the ScrollView returns to the top. I've specified the height of every view in the hierarchy. How can I fix?

Keep in mind that ScrollViews must have a bounded height in order to work, since they contain unbounded-height children into a bounded container (via a scroll interaction). In order to bound the height of a ScrollView, either set the height of the view directly (discouraged) or make sure all parent views have bounded height.

Code (try on snack.expo.io):

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

const { width, height } = Dimensions.get('window');
const gutterSize = 10;
const columns = 2;
const colWidth = (width / columns) - (gutterSize * columns) + (gutterSize / 2);
const style = {width: colWidth, height: 100, backgroundColor: '#0f0', marginLeft: gutterSize, marginTop: gutterSize, position: 'absolute'};

export default class App extends Component {

  render() {
    return (
      <View style={{height: height, backgroundColor: '#00f'}}>
        <ScrollView style={{backgroundColor: '#f00', height: 3000, position: 'absolute', width: width, top: 20}}>
          <View style={[style, {height: 100}]} />
          <View style={[style, {height: 120, left: 155}]} />
          <View style={[style, {height: 190, top: 110}]} />
          <View style={[style, {height: 120, left: 155, top: 130}]} />
          <View style={[style, {height: 190, left: 155, top: 260}]} />
          <View style={[style, {height: 80, top: 310}]} />
          <View style={[style, {height: 280, top: 400}]} />
          <View style={[style, {height: 300, left: 155, top: 460}]} />
        </ScrollView>
      </View>
    );
  }
}
Jon
  • 3,208
  • 1
  • 19
  • 30
  • 1
    Just a quick question about this comment you wrote: *"I do not think this is possible to do using flexbox"* - Why do you think this isn't possible? Your example is very basic, so I may be overlooking some nuances/edge cases, but my first thought would be that this is doable. – Michael Cheng Jul 21 '17 at 01:10
  • @MichaelCheng. I didn't see any pure flexbox solutions to this [SO post](https://stackoverflow.com/questions/33552782/what-is-the-best-way-to-create-an-asymmetrical-two-column-grid-with-dynamic-cont), so didn't think it was possible. Vertical 1 column was easy. I didn't think to actually split the columns as in David's solution. – Jon Jul 21 '17 at 02:08
  • David's answer was exactly what I was thinking about as to how to solve it, but I didn't want to put time into writing up that answer if it turned out that you used absolute positioning for some special reason. Glad to see that his solution was what you were looking for. – Michael Cheng Jul 21 '17 at 02:30

2 Answers2

1

using flexDirection: 'row', this can be easily solved. Tested in Expo.

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

const { width, height } = Dimensions.get('window');
const gutterSize = 10;
const columns = 2;
const colWidth = (width / columns) - (gutterSize * columns) + (gutterSize / 2);
const style = {width: colWidth, height: 100, backgroundColor: '#0f0', marginLeft: gutterSize, marginTop: gutterSize};

export default class App extends Component {

  render() {
    return (
      <View style={{height: height, backgroundColor: '#00f'}}>
        <ScrollView style={{backgroundColor: '#f00', width: width, top: 20}}>
          <View style={{flexDirection: 'row'}}>
            <View>
              <View style={[style, {height: 100}]} />
              <View style={[style, {height: 110}]} />
              <View style={[style, {height: 120}]}/>
              <View style={[style, {height: 130}]} />
            </View>
            <View>
              <View style={[style, {height: 140}]} />
              <View style={[style, {height: 90}]}/>
              <View style={[style, {height: 150}]}/>
              <View style={[style, {height: 270}]}/>
            </View>
          </View>
        </ScrollView>
      </View>
    );
  }
}
Jon
  • 3,208
  • 1
  • 19
  • 30
David
  • 15,894
  • 22
  • 55
  • 66
0

I solved it by adding the bounces prop and setting it to false:

<ScrollView bounces={false}></ScrollView>
spedy
  • 2,200
  • 25
  • 26