vertical ScrollView with wrapped row in React Native

5.7k views Asked by At

I'm new to React Native, and struggling to get my ScrollView working.

I'm trying to have a vertically scrollable list of TouchableOpacity components that are arranged in pairs across the page, e.g.

view arrangement

This is how the app looks when I wrap the TouchableOpacity components in a View, but (obviously) it is not scrollable. If I change the View to a ScrollView, the components are no longer arranged correctly, they now look like this:

Broken ScrollView

They are still not scrollable, and also the layout is no longer working correctly.

So far (and there may be a better way of achieving this?) I've attempted to create my layout by setting the container to have flexDirection: row, with wrap turned on, and sizing the sub components appropriately to fit two across the screen.

Approximation of the code i'm using is:

export default class App extends React.Component {
  render() {
    return (
      <ScrollView style={styles.container}>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
              <Text style={styles.buttonText}>TouchableOpacity</Text>
          </TouchableOpacity>
      </ScrollView>
    );

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#fff',
      height: 3440,
      minHeight: 3440,
      width: 1280,
      minWidth: 1280,
      flexGrow: 1,
      flexDirection: 'row',
      flexWrap: 'wrap'
  },
    newButton: {
       height: 180,
       width: 620,
        margin: 5,
        borderRadius: 10,
        alignContent: 'center',
        justifyContent: 'center',
      backgroundColor: 'darkblue'
    },
    buttonText: {
      alignSelf: 'center',
        fontSize: 36,
        color: 'white',
    }
});
2

There are 2 answers

0
Khemraj Sharma On BEST ANSWER

This view is a Grid View.

Try this code. (reference)

var TestCmp = React.createClass({
    getInitialState: function() {
      var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
      var data = Array.apply(null, {length: 20}).map(Number.call, Number);
      return {
        dataSource: ds.cloneWithRows(data),
      };
    },

    render: function() {
      return (
        <ListView contentContainerStyle={styles.list}
          dataSource={this.state.dataSource}
          renderRow={(rowData) => <Text style={styles.item}>{rowData}</Text>}
        />
      );
    }
});

Here's the style object:

var styles = StyleSheet.create({
    list: {
        flexDirection: 'row',
        flexWrap: 'wrap'
    },
    item: {
        backgroundColor: 'red',
        margin: 3,
        width: 100
    }
});

We set items in a wrapping row, and the we set the width of each child object.

Screenshot

There are lot of dependencies. That will make your work easy.

  1. https://github.com/GeekyAnts/react-native-easy-grid#readme
  2. https://github.com/idibidiart/react-native-responsive-grid#readme
  3. https://github.com/phil-r/react-native-grid-component#readme
  4. https://github.com/yelled3/react-native-grid-example
  5. https://github.com/toystars/react-native-layout-grid#readme
0
Milan Korangi On
  <ScrollView>
    <View style={styles.container}>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => doAThing()} style={styles.newButton}>
          <Text style={styles.buttonText}>TouchableOpacity</Text>
      </TouchableOpacity>
    </View>
  </ScrollView>