10

I'm trying to create a menu for my application in React-Native which should have multiple icons in the below way enter image description here

The icons should be in the same row and wrapped so that if screen is bigger more icons will be on the same row.

My current code is as follows

import React from 'react';
import { StyleSheet, View } from 'react-native';

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.box}></View>
        <View style={styles.box}></View>
        <View style={styles.box}></View>
        <View style={styles.box}></View>
        <View style={styles.box}></View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'space-evenly',
    flexDirection: 'row',
    flexWrap: 'wrap',
    paddingTop: 40
  },
  box: {
    width: 100,
    height: 100,
    backgroundColor: 'aqua',
    margin: 10,
  }
});

The current output is as below

enter image description here

The children count may change in the future but i need to have spacing on the sides, using flex-start will give the below output which is wrong.i want to have spacing in both sides as well.

enter image description here

How do i align it to left and have the items with even space around as the image above ?

Guruparan Giritharan
  • 15,660
  • 4
  • 27
  • 50
  • `alignItems: 'center'` would center the blocks. Change it to `alignItems: 'left'` and it should align to the left – Aniket G Mar 07 '19 at 05:04
  • its react-native and left is not supported :) – Guruparan Giritharan Mar 07 '19 at 05:05
  • Right. Change `justifyContent: 'space-evenly'` to `justifyContent: 'flex-start'` https://stackoverflow.com/questions/36008969/how-to-justify-left-right-center-each-child-independently – Aniket G Mar 07 '19 at 05:06
  • Possible duplicate of [How to justify (left, right, center) each child independently?](https://stackoverflow.com/questions/36008969/how-to-justify-left-right-center-each-child-independently) – Aniket G Mar 07 '19 at 05:07
  • @AniketG flext-start i'm trying to use the same row so flex start will have more space at the right which is the problem, as this is the same row its not a duplicate – Guruparan Giritharan Mar 07 '19 at 05:10

3 Answers3

3

for Box use Dimensions, Based on screen width divide box width

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'flex-start',
    flexDirection: 'row',
    flexWrap: 'wrap',
    paddingTop: 40
   },
  box: {
    width: (Dimensions.get('window').width / 3) - 20, /* minus some value for adjust the gap between boxes */
    height: 100,
    backgroundColor: 'aqua',
    margin: 10,
  }
});
0

One option is to add extra 'fake' boxes which will fill the available space in last row:

<View style={styles.box}></View>
<View style={styles.box}></View>
<View style={styles.box}></View>
<View style={styles.box}></View>
<View style={styles.box}></View>
<View style={[styles.box, styles.boxFake]}></View>
<View style={[styles.box, styles.boxFake]}></View>
<View style={[styles.box, styles.boxFake]}></View>
<View style={[styles.box, styles.boxFake]}></View>
<View style={[styles.box, styles.boxFake]}></View>

// reset all styles like backgroundColor, border, etc.
const styles = StyleSheet.create({
  boxFake: {
    backgroundColor: 'transparent'
  }
});

You can easy calculate the number of necessary 'fake' boxes by the formula:

fakeBoxes = boxesPerRow - totalBoxes % boxesPerRow

King Julien
  • 10,981
  • 24
  • 94
  • 132
0

I took a different approach by using another view as a wrapper and doing the calculation of its width, this is easier to decide the column widths. The only problem is that we should know the width of the item, wont be a problem in my case. The code will be as below.

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

export default class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      width: 110
    };
  }

  render() {
    //width of child is 110
    const width = `${100 / parseInt(this.state.width / 110)}%`;
    return (
      <ScrollView>
        <View style={styles.container} onLayout={this.onLayout.bind(this)}>
          <View style={[styles.wrapper, { width: width }]}>
            <View style={styles.box}></View>
          </View>
          <View style={[styles.wrapper, { width: width }]}>
            <View style={styles.box}></View>
          </View>
          <View style={[styles.wrapper, { width: width }]}>
            <View style={styles.box}></View>
          </View>
          <View style={[styles.wrapper, { width: width }]}>
            <View style={styles.box}></View>
          </View>
          <View style={[styles.wrapper, { width: width }]}>
            <View style={styles.box}></View>
          </View>
        </View>
      </ScrollView>
    );
  }

  onLayout(e) {
    if (this.state.width !== e.nativeEvent.layout.width) {
      this.setState({
        width: e.nativeEvent.layout.width
      })
    }
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'flex-start',
    justifyContent: 'flex-start',
    flexDirection: 'row',
    flexWrap: 'wrap',
    paddingTop: 40
  },
  box: {
    width: 100,
    height: 100,
    backgroundColor: 'green',
  },
  wrapper: {
    marginVertical: 10, alignItems: 'center'
  }
});
Guruparan Giritharan
  • 15,660
  • 4
  • 27
  • 50