8

How can I make something like

enter image description here

in React Native?

I have tried simply with flexDirection: row and then a <View> for every single row.

But I need to define the number of seats in every row and change the horizontal position for every second row. However, some rows don't differ in horizontal position, so I actually have to define whether the row is moved a bit horizontally.

I guess it could be done with

const rows = [
  { numSeats: 10, shifted: true },
  { numSeats: 11, shifted: false },
  { numSeats: 7, shifted: true },
  { numSeats: 10, shifted: true },
]

and then loop through all rows

<View>
  {rows.map((row, i) => (
    <View style={{ flexDirection: 'row' }}>
      {Array(row.numSeats).fill(null).map(_ => (
        <View style={{ width: 20, height: 20 }} />
      )}
    </View>
  )}
}

but I don't know if this is a clever way nor how to shift the seats relative to the other rows.

Jamgreen
  • 10,329
  • 29
  • 113
  • 224

4 Answers4

1

Rather then shifting all row maybe you can consider using justifyContent: center. Since the number of the seats - I assume - is known you can create fixed sized boxes for each row and centering would get them align as you needed.

On the other hand some seats have different margins in between so I suggest you to have that in your data and but margins according to that data.

bennygenel
  • 23,896
  • 6
  • 65
  • 78
0

Here i have justifyContent: 'center' and alignItems: 'center' to view to place item to center.

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

export default class App extends Component {
  render() {
      const rows = [
      { numSeats: 10, shifted: true },
      { numSeats: 11, shifted: false },
      { numSeats: 7, shifted: true },
      { numSeats: 10, shifted: true },
    ];
    return (
      <View style={{ padding: 50 }}>
          {rows.map((row) => {
              return (
                <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
                    {Array(row.numSeats).fill(null).map(() => {
                        return <View style={{ width: 20, height: 20, backgroundColor: 'orange', margin: 5 }} />;
                    }
                )}
            </View>     
         );
          })
         }
      </View>
      );
    }
  }
Dinesh Katwal
  • 930
  • 1
  • 14
  • 25
0

Consider this: you have not the only layout works, different seats will be filled with different color, how do you handle this?you really have to point out which seat in which row is "VIP", which seat in which row is "ordered", which seat in which row is "normal"( or any other classification ), so this floor plan will be a two-dimensional array mapping.like this:

// 1:ordered 2:VIP 3:normal 4:unreal(for 15th row gaps)
const seatMap = [
  [2,2,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,2,2], // 1st row
  [2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,2,2,2], // 2st row
  ...,
  [3,3,3,3,3,4,3,3,3,3,3,3,3,3,3,4,3,3,3,3,3], // 15th
  [3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3], // 16th
  [3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3]  // 17th
]

render(){
  return (
    <View>
      {
        seatMap.map(
          (row,rowIndex) => <View>
            {
              row.map(
                (type,colIndex)=><SeatBlock 
                                    type={ type } 
                                    row={ rowIndex } 
                                    col={ colIndex }/>
              )
            }
          </View>
        )
      }
    </View>
  )
}

pay attention to type 4, it's not really a 'seat type', it's a gap,we render it as a gap instead of a seat, and you can define 5 or 6 for bigger or smaller gap unit.it's flexible.

you can check full code below.

<div data-snack-id="rJnoL_Xn-" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="dark" style="overflow:hidden;background:#212733;border:1px solid rgba(0,0,0,.16);border-radius:4px;height:505px;width:100%"></div>
<script async src="https://snack.expo.io/embed.js"></script>
Oboo Cheng
  • 4,250
  • 3
  • 24
  • 29
0

You could use an approach similar to this:

seatsPerRow.map((numSeats, index) => {
  return (
    <View style={{flex: 1, flexDirection: 'row', justifyContent: 'space-between'}}>
      <Text>{index}</Text>
      <View style={{flexDirection: 'row'}}>
      {
        Array(numSeats).fill(null).map(_ => {
         return <SeatSquare />
        })            
      }     
      </View>
      <Text>{index}</Text>
    </View>  
  )
});

Basically, setting justifyContent to space-between should keep the row indices to the side and center the row containing the seats.

Mateo Hrastnik
  • 533
  • 1
  • 7
  • 20