React native Demo Food Dishes List UI , DRY , KISS

9 min read

Relsell Global : Cross platform development using React Native

Dear friends

Congrats for taking time to grow yourself. People are waiting for your to develop something right.

In our last tutorial , we made a sample Flatlist and displayed it on screen. Lets do some improvements to the UI and try to build it. And we say leaning via repetitions.

Food Dishes List UI

So in the code for the referenced tutorial i wrote earlier , there is a customised list item MyListItem is used. we need to improve its code, specifically styles.

Before starting , I would like to introduce you to a lib which allow to you give dimensions in percentages of screen width or height . Doing this will make your UI responsive. Link

You need to install this library in your project.

Iteration 1: Build basic UI

First step in improving a UI is colors , So we are going to improve our styles and text items. For getting the colors that are used in creating each row item , you may like to use , a color picker plugin for chrome or firefox,

Also we are having the image file in our assets folder ,

import React, {Component} from 'react';
import {
  AppRegistry,
  FlatList,
  StyleSheet,
  Text,
  View,
  Image,
} from 'react-native';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
const dataSource = [
  {
    key: 'Anil',
    title: 'CEO',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Sunil',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Kittu',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
  {
    key: 'Kittu',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
];

renderItemFunc = ({item}) => {
  return <Text style={styles.item}>{item.key}</Text>;
};

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={dataSource}
          renderItem={({item}) => (
            <View>
              <MyListItem
                title={item.title}
                name={item.key}
                itemStyle={styles}
                pp={{uri: item.profilepic}}
              />
            </View>
          )}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
  },
  itemwrapper: {
    elevation: 1,
    borderRadius: wp('3%'),
    marginTop: wp('5%'),
    marginLeft: wp('8%'),
    marginRight: wp('4%'),
  },
  item: {
    fontSize: hp('3%'),
    color: '#9077DA',
  },
  itemtitle: {
    flex: 1,
    padding: 12,
    fontSize: 12,
    height: 30,
    fontStyle: 'italic',
  },
  itemImage: {
    height: hp('15%'),
    width: wp('40%'),
    borderRadius: wp('3%'),
  },
  headingText: {
    fontSize: 50,
    textAlign: 'center',
  },
});

class MyListItem extends React.PureComponent {
  render() {
    return (
      <View
        style={[styles.itemwrapper, {flexDirection: 'row', padding: wp('2%')}]}>
        <View
          style={{
            position: 'absolute',
            marginLeft: wp('-5%'),
            marginTop: hp('4%'),
          }}>
          <Image
            resizeMode={'cover'}
            style={this.props.itemStyle.itemImage}
            source={require('./assets/images/imagefood.png')}
          />
        </View>
        <View style={{flex: 0.8}}></View>
        <View style={[{flex: 1, paddingBottom: hp('2.5%')}]}>
          <Text style={[this.props.itemStyle.item, {fontWeight:'bold',fontSize: hp('4.6%')}]}>
            Paneer Tikka
          </Text>
          <View style={{flexDirection: 'row'}}>
            <Text style={{marginTop: hp('1%'), fontSize: hp('1.5%')}}>
              City{' '}
            </Text>
            <Text style={{marginTop: hp('1%'), fontSize: hp('1.5%')}}>
              Khyaban shabaz (karachi)
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{flex: 1, fontSize: hp('1.5%'), color: '#b3b6bc'}}>
              Check in time
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.5%'),
                color: '#b3b6bc',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{flex: 1, fontSize: hp('1.5%'), color: '#b3b6bc'}}>
              Check out time
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.5%'),
                color: '#b3b6bc',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{flex: 1, fontSize: hp('1.5%'), color: '#b3b6bc'}}>
              People
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.5%'),
                color: '#b3b6bc',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{flex: 1, fontSize: hp('1.5%'), color: '#b3b6bc'}}>
              Occassion
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.5%'),
                color: '#b3b6bc',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              Family Dinner
            </Text>
          </View>
        </View>
      </View>
    );
  }
}

On pixel 2 device your screen will appear like

Iteration 2 : Widgets Alignments

Lets improve the UI Further , and try to update alignments of different ui widget on screens. Having right alignments makes our UI looks more professional , Fellow designers invest lot of crucial time to develop eye catching UI, but still we are developers , our tools and IDE and entirely different from their’s. So now after making improvements the code will look like

import React, {Component} from 'react';
import {
  AppRegistry,
  FlatList,
  StyleSheet,
  Text,
  View,
  Image,
} from 'react-native';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
const dataSource = [
  {
    key: 'Anil',
    title: 'CEO',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Sunil',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Kittu',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
  {
    key: 'Kittu',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
];

renderItemFunc = ({item}) => {
  return <Text style={styles.item}>{item.key}</Text>;
};

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={dataSource}
          renderItem={({item}) => (
            <View>
              <MyListItem
                title={item.title}
                name={item.key}
                itemStyle={styles}
                pp={{uri: item.profilepic}}
              />
            </View>
          )}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
  },
  itemwrapper: {
    elevation: 1,
    borderRadius: wp('3%'),
    marginTop: wp('5%'),
    marginLeft: wp('8%'),
    marginRight: wp('4%'),
  },
  item: {
    fontSize: hp('3%'),
    color: '#9077DA',
  },
  itemtitle: {
    flex: 1,
    padding: 12,
    fontSize: 12,
    height: 30,
    fontStyle: 'italic',
  },
  itemImage: {
    height: hp('15%'),
    width: wp('40%'),
    borderRadius: wp('3%'),
  },
  headingText: {
    fontSize: 50,
    textAlign: 'center',
  },
});

class MyListItem extends React.PureComponent {
  render() {
    return (
      <View
        style={[styles.itemwrapper, {flexDirection: 'row', padding: wp('2%')}]}>
        <View
          style={{
            position: 'absolute',
            marginLeft: wp('-5%'),
            marginTop: hp('4%'),
          }}>
          <Image
            resizeMode={'cover'}
            style={this.props.itemStyle.itemImage}
            source={require('./assets/images/imagefood.png')}
          />
        </View>
        <View style={{flex: 0.8}}></View>
        <View style={[{flex: 1, paddingBottom: hp('2.5%')}]}>
          <Text style={[this.props.itemStyle.item, {fontFamily:'Montserrat-Italic',fontSize: hp('4.6%')}]}>
            Paneer Tikka
          </Text>
          <View style={{flexDirection: 'row',alignItems:'flex-start',marginBottom:hp('1%')}}>
            <View style={{}}>
            <Image
            resizeMode={'contain'}
            style={{marginRight:wp('1%'),width:wp('4%'),height:wp('4%')}}
            source={require('./assets/images/location_icon.png')}
            />
          </View>
          
            <Text style={{fontFamily:'Montserrat-Regular',color: '#b3b6bc', fontSize: hp('1.8%')}}>
              Khyaban shabaz (karachi)
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.8%'), color: '#b3b6bc'}}>
              Check in time
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.8%'),
                color: '#b3b6bc',
                fontFamily:'Montserrat-Regular',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.8%'), color: '#b3b6bc'}}>
              Check out time
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.8%'),
                color: '#b3b6bc',
                textAlign: 'right',
                fontFamily:'Montserrat-Regular',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.8%'), color: '#b3b6bc'}}>
              People
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.8%'),
                color: '#b3b6bc',
                textAlign: 'right',
                paddingRight:wp('5%'),
                fontFamily:'Montserrat-Regular'
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row'}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.8%'), color: '#b3b6bc'}}>
              Occassion
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.8%'),
                color: '#b3b6bc',
                fontFamily:'Montserrat-Regular',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              Family Dinner
            </Text>
          </View>
        </View>
      </View>
    );
  }
}

Output will be as

Iteration 3: Custom fonts and Alignments

Let’s improve UI further, and try to use custom fonts , you may use free font service like Google web fonts to get fonts files, and you may like to visit a nice article on medium. For android Native programming you may visit my earlier blog

And thats how our code will become after this ,

import React, {Component} from 'react';
import {
  AppRegistry,
  FlatList,
  StyleSheet,
  Text,
  View,
  Image,
} from 'react-native';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
const dataSource = [
  {
    key: 'Anil',
    title: 'CEO',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Sunil',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Kittu',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
  {
    key: 'Kittu2',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
];

renderItemFunc = ({item}) => {
  return <Text style={styles.item}>{item.key}</Text>;
};

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={dataSource}
          renderItem={({item}) => (
            <View>
              <MyListItem
                title={item.title}
                name={item.key}
                itemStyle={styles}
                pp={{uri: item.profilepic}}
              />
            </View>
          )}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
  },
  itemwrapper: {
    elevation: 1,
    borderRadius: wp('3%'),
    marginTop: wp('5%'),
    marginLeft: wp('8%'),
    marginRight: wp('4%'),
  },
  item: {
    fontSize: hp('3%'),
    color: '#9077DA',
  },
  itemtitle: {
    flex: 1,
    padding: 12,
    fontSize: 12,
    height: 30,
    fontStyle: 'italic',
  },
  itemImage: {
    height: hp('15%'),
    width: wp('40%'),
    borderRadius: wp('3%'),
  },
  headingText: {
    fontSize: 50,
    textAlign: 'center',
  },
});

class MyListItem extends React.PureComponent {
  render() {
    return (
      <View
        style={[styles.itemwrapper, {flexDirection: 'row', padding: wp('2%')}]}>
        <View
          style={{
            position: 'absolute',
            marginLeft: wp('-5%'),
            marginTop: hp('4%'),
          }}>
          <Image
            resizeMode={'cover'}
            style={this.props.itemStyle.itemImage}
            source={require('./assets/images/imagefood.png')}
          />
        </View>
        <View style={{flex: 0.8}}></View>
        <View style={[{flex: 1, paddingBottom: hp('2.5%')}]}>
          <Text style={[this.props.itemStyle.item, {fontFamily:'Montserrat-SemiBold',fontSize: hp('4%')}]}>
            Paneer Tikka
          </Text>
          <View style={{flexDirection: 'row',alignItems:'flex-start',marginBottom:hp('1%')}}>
            <View style={{}}>
            <Image
            resizeMode={'contain'}
            style={{marginRight:wp('1%'),width:wp('4%'),height:wp('4%')}}
            source={require('./assets/images/location_icon.png')}
            />
          </View>
          
            <Text style={{fontFamily:'Montserrat-Regular',color: '#b3b6bc', fontSize: hp('1.6%')}}>
              Khyaban shabaz (karachi)
            </Text>
          </View>
          <View style={{flexDirection: 'row',marginTop:hp('0.5%')}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.6%'), color: '#b3b6bc'}}>
              Check in time
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.6%'),
                color: '#b3b6bc',
                fontFamily:'Montserrat-Regular',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row',marginTop:hp('0.5%')}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.6%'), color: '#b3b6bc'}}>
              Check out time
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.6%'),
                color: '#b3b6bc',
                textAlign: 'right',
                fontFamily:'Montserrat-Regular',
                paddingRight:wp('5%')
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row',marginTop:hp('0.5%')}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.6%'), color: '#b3b6bc'}}>
              People
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.6%'),
                color: '#b3b6bc',
                textAlign: 'right',
                paddingRight:wp('5%'),
                fontFamily:'Montserrat-Regular'
              }}>
              03.00.00
            </Text>
          </View>
          <View style={{flexDirection: 'row',marginTop:hp('0.5%')}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.6%'), color: '#b3b6bc'}}>
              Occassion
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.6%'),
                color: '#b3b6bc',
                fontFamily:'Montserrat-Regular',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              Family Dinner
            </Text>
          </View>
        </View>
      </View>
    );
  }
}

Visual output of the above code is

Iteration 5 : DRY AND KISS

Now use DRY principle to make your life easy and you should be proud of writing a clean code.

if we carefully scan our existing code , we will find that some code is sort of repeated code, we identify that code and add them to a separate function. Wherever required we call this function. That way in future if we need to change the ux we have to make changes at a single place.

Final code

import React, {Component} from 'react';
import {
  AppRegistry,
  FlatList,
  StyleSheet,
  Text,
  View,
  Image,
} from 'react-native';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
const dataSource = [
  {
    key: 'Anil',
    title: 'CEO',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Sunil',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fanil.jpg?alt=media&token=78b94b84-55df-4c7d-aa69-109c3753dfa0',
  },
  {
    key: 'Kittu',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
  {
    key: 'Kittu2',
    title: 'DIRECTOR',
    profilepic:
      'https://firebasestorage.googleapis.com/v0/b/rnfirebasedemo-a238a.appspot.com/o/profiles%2Fkittu.jpg?alt=media&token=7496b5dc-619b-4998-be97-73815d567b85',
  },
];

renderItemFunc = ({item}) => {
  return <Text style={styles.item}>{item.key}</Text>;
};

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={dataSource}
          renderItem={({item}) => (
            <View>
              <MyListItem
                title={item.title}
                name={item.key}
                itemStyle={styles}
                pp={{uri: item.profilepic}}
              />
            </View>
          )}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
  },
  itemwrapper: {
    elevation: 1,
    borderRadius: wp('3%'),
    marginTop: wp('5%'),
    marginLeft: wp('8%'),
    marginRight: wp('4%'),
  },
  item: {
    fontSize: hp('3%'),
    color: '#9077DA',
  },
  itemtitle: {
    flex: 1,
    padding: 12,
    fontSize: 12,
    height: 30,
    fontStyle: 'italic',
  },
  itemImage: {
    height: hp('15%'),
    width: wp('40%'),
    borderRadius: wp('3%'),
  },
  headingText: {
    fontSize: 50,
    textAlign: 'center',
  },
});

class MyListItem extends React.PureComponent {
  render() {
    return (
      <View
        style={[styles.itemwrapper, {flexDirection: 'row', padding: wp('2%')}]}>
        <View
          style={{
            position: 'absolute',
            marginLeft: wp('-5%'),
            marginTop: hp('4%'),
          }}>
          <Image
            resizeMode={'cover'}
            style={this.props.itemStyle.itemImage}
            source={require('./assets/images/imagefood.png')}
          />
        </View>
        <View style={{flex: 0.8}}></View>
        <View style={[{flex: 1, paddingBottom: hp('2.5%')}]}>
          <Text style={[this.props.itemStyle.item, {fontFamily:'Montserrat-SemiBold',fontSize: hp('4%')}]}>
            Paneer Tikka
          </Text>
          <View style={{flexDirection: 'row',alignItems:'flex-start',marginBottom:hp('1%')}}>
            <View style={{}}>
            <Image
            resizeMode={'contain'}
            style={{marginRight:wp('1%'),width:wp('4%'),height:wp('4%')}}
            source={require('./assets/images/location_icon.png')}
            />
          </View>
          
            <Text style={{fontFamily:'Montserrat-Regular',color: '#b3b6bc', fontSize: hp('1.6%')}}>
              Khyaban shabaz (karachi)
            </Text>
          </View>
          {this.renderRepeatedTimings({arr:['Check In Time','03:00,00']})}
          {this.renderRepeatedTimings({arr:['Check Out Time','04:00,00']})}
          {this.renderRepeatedTimings({arr:['People','04']})}
          {this.renderRepeatedTimings({arr:['Occassion','Family Dinner']})}
        </View>
      </View>
    );
  }
 
  renderRepeatedTimings(arrObj){
    return(
      <View style={{flexDirection: 'row',marginTop:hp('0.5%')}}>
            <Text style={{fontFamily:'Montserrat-Regular',flex: 1, fontSize: hp('1.5%'), color: '#b3b6bc'}}>
              {arrObj.arr[0]}
            </Text>
            <Text
              style={{
                flex: 1,
                fontSize: hp('1.5%'),
                color: '#b3b6bc',
                fontFamily:'Montserrat-Regular',
                textAlign: 'right',
                paddingRight:wp('5%')
              }}>
              {arrObj.arr[1]}
            </Text>
          </View>
          
    );
  }


}

Its a long tutorial , help me find if something is missing. I will update. Thanks for helping.

Source code for the app : Link

This brings us to the end of blog. Thanks for investing time in yourself. World is still waiting to see you build something great.

Have a good day

Leave a Reply

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