Flex box Layout, Flex Direction

The Flexible Box Module, usually referred to as flexbox, was designed as a one-dimensional layout model, and as a method that could offer space distribution between items in an interface and powerful alignment capabilities

Let’s create a ReactNative Calculator, I prefer to do this calculator design because it gives us better understanding of nested layouts as well as in creating flexible (responsive) design.

Lets go ahead and create a new project

$ react-native init MyCalculatorProj

Open this folder in visual studio code (Make sure to close the metro server if it is already running)

In the terminal tab execute $ react-native run-android

As usual clear the App.js file and replace with

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

const style = StyleSheet.create({
  container:{
    flex:1,
    backgroundColor:'#420C01'
  },
  resultContainer:{
    flex:1
  },
  btnsContainer:{
    flex:4,
    backgroundColor:'#DA7803'
  }
});

export default class App extends Component{
  constructor(props){
    super(props);
  }

  render(){
    return <View style={style.container}>
      <View style={style.resultContainer}></View>
      <View style={style.btnsContainer}></View>
    </View>
  }
}

The calculator design comprises 3 container boxes,

container:{flex:1,backgroundColor:'#420C01'} is a main wrapper of other 2 containers i.e., resultsContainer and btnsContainer.

This produces following output

  • What makes this partition?, container which is a wrapper having flex value 1, It occupies entire screen with backgroundColor : #420C01
  • The other containers resultsContainer with flex value 1 and btnsContainer with flex value 4 makes the entire screen area divided in to 5
  • resultsContainer takes 1/5 of screen’s height and btnsContainer takes 4/5 of screen’s hight. For width value, we can safely assume screens entire width.
  • The partition happens in vertical direction i.e., height because the parent container flexDirection is ‘column‘ . We did not specify it explicitly because default flexDirection is always column. (We can say in vertical direction), If partition has to happen in horizontal direction we can specify flexDirection:'row' . we will see that in a moment.

Let’s start adding Input buttons of the calculator. We will split the btnsContainer in to 5 (in vertical direction), create a rule btnsRow:{flex:1}

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

const style = StyleSheet.create({
  container:{
    flex:1,
    backgroundColor:'#420C01'
  },
  resultContainer:{
    flex:1
  },
  btnsContainer:{
    flex:4,
    backgroundColor:'#DA7803'
  },
  btnsRow:{
    flex:1
  }
});

export default class App extends Component{
  constructor(props){
    super(props);
  }

  render(){
    return <View style={style.container}>
      <View style={style.resultContainer}></View>
      <View style={style.btnsContainer}>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
      </View>
    </View>
  }
}

  • We are going to add following buttons in each row.
  • AC, +/-, %, /
  • 7,8,9,x
  • 4,5,6,-
  • 1,2,3,+
  • 0, . , =

But to make this happen, add the flexDirection:'row' to btnsRow

Create following rules inputBtn and inputBtnText

The updated code would be

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

const style = StyleSheet.create({
  container:{
    flex:1,
    backgroundColor:'#420C01'
  },
  resultContainer:{
    flex:1
  },
  btnsContainer:{
    flex:4,
    backgroundColor:'#DA7803'
  },
  btnsRow:{
    flex:1,
    flexDirection:'row'
  },
  inputBtn:{
    flex:1,
    backgroundColor:'#420C01',
    borderWidth:2,
    borderColor:'#FFFFFF',
    borderRadius:4,
    justifyContent:'center',
    alignItems:'center',
    margin:4
  },
  inputBtnText:{
    color:'#FFFFFF',
    fontSize:20,
    fontWeight:'bold'
  }
});

export default class App extends Component{
  constructor(props){
    super(props);
  }

  render(){
    return <View style={style.container}>
      <View style={style.resultContainer}>
        
      </View>
      <View style={style.btnsContainer}>
        <View style={style.btnsRow}>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>AC</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>+/-</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>%</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>/</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
        <View style={style.btnsRow}></View>
      </View>
    </View>
  }
}

This produces the below output

We have added the flexDirection:’row’ to btnsRow, this will force its children inputBtn container(s) in horizontal direction. Remember flexDirection rule is always enforced to the child container.

Let’s complete all buttons. We use TouchableOpacity Component instead of Button, TouchableOpacity supports all button events such as onPress and acts as a layout container for a Text.

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

const style = StyleSheet.create({
  container:{
    flex:1,
    backgroundColor:'#420C01'
  },
  resultContainer:{
    flex:1
  },
  btnsContainer:{
    flex:4,
    backgroundColor:'#DA7803'
  },
  btnsRow:{
    flex:1,
    flexDirection:'row'
  },
  inputBtn:{
    flex:1,
    backgroundColor:'#420C01',
    borderWidth:2,
    borderColor:'#FFFFFF',
    borderRadius:4,
    justifyContent:'center',
    alignItems:'center',
    margin:4
  },
  inputBtnEqual:{
    flex:2,
    backgroundColor:'#420C01',
    borderWidth:2,
    borderColor:'#FFFFFF',
    borderRadius:4,
    justifyContent:'center',
    alignItems:'center',
    margin:4
  },
  inputBtnText:{
    color:'#FFFFFF',
    fontSize:20,
    fontWeight:'bold'
  }
});

export default class App extends Component{
  constructor(props){
    super(props);
  }

  render(){
    return <View style={style.container}>
      <View style={style.resultContainer}>

      </View>
      <View style={style.btnsContainer}>
        <View style={style.btnsRow}>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>AC</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>+/-</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>%</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>/</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>7</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>8</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>9</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>X</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>4</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>5</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>6</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>-</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>1</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>2</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>3</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>+</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>0</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>.</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtnEqual}>
            <Text style={style.inputBtnText}>=</Text>
          </TouchableOpacity>
        </View>
      </View>
    </View>
  }
}

The output will be

I have added separate rule for “=” button. i.e., with flex value 2 to get the above output.

Finally add the resultText rule and complete the code

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

const style = StyleSheet.create({
  container:{
    flex:1,
    backgroundColor:'#420C01'
  },
  resultContainer:{
    flex:1
  },
  btnsContainer:{
    flex:4,
    backgroundColor:'#DA7803'
  },
  btnsRow:{
    flex:1,
    flexDirection:'row'
  },
  inputBtn:{
    flex:1,
    backgroundColor:'#420C01',
    borderWidth:2,
    borderColor:'#FFFFFF',
    borderRadius:4,
    justifyContent:'center',
    alignItems:'center',
    margin:4
  },
  inputBtnEqual:{
    flex:2,
    backgroundColor:'#420C01',
    borderWidth:2,
    borderColor:'#FFFFFF',
    borderRadius:4,
    justifyContent:'center',
    alignItems:'center',
    margin:4
  },
  inputBtnText:{
    color:'#FFFFFF',
    fontSize:20,
    fontWeight:'bold'
  },
  resultText:{
    color:'#FFFFFF',
    fontSize:70,
    textAlign:'right',
    margin:10
  }
});

export default class App extends Component{
  constructor(props){
    super(props);
  }

  render(){
    return <View style={style.container}>
      <View style={style.resultContainer}>
          <Text style={style.resultText}>0</Text>
      </View>
      <View style={style.btnsContainer}>
        <View style={style.btnsRow}>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>AC</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>+/-</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>%</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>/</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>7</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>8</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>9</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>X</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>4</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>5</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>6</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>-</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>1</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>2</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>3</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>+</Text>
          </TouchableOpacity>
        </View>
        <View style={style.btnsRow}>
        <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>0</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtn}>
            <Text style={style.inputBtnText}>.</Text>
          </TouchableOpacity>
          <TouchableOpacity style={style.inputBtnEqual}>
            <Text style={style.inputBtnText}>=</Text>
          </TouchableOpacity>
        </View>
      </View>
    </View>
  }
}

Download source code

Leave a Reply

Your email address will not be published. Required fields are marked *