Insta4, React Native Icons

  For developing mobile application like Instagram with react native and typescript, this writing explains how to use React Native Icons. This article is continued one from previous article.



1. Install and set up for icons

$ cd InstaTest

$ npm i react-native-vector-icons 
$ npm i -D @types/react-native-vector-icons

$ cd ios
$ npx pod-install
$ cd ..
  • If your Metro server is running, you need to escape from it first by ctrl + c. When Metro is running, packages are locked so other package cannot be added.

  • Set up for iOS : Edit the ios/projectName/Info.plist
  • Below <key>UIAppFonts</key> should be added.
ios/InstaTest/Info.plist
  ...

    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
    <key>UIAppFonts</key>
    <array>
        <string>AntDesign.ttf</string>
        <string>Entypo.ttf</string>
        <string>EvilIcons.ttf</string>
        <string>Feather.ttf</string>
        <string>FontAwesome.ttf</string>
        <string>FontAwesome5_Brands.ttf</string>
        <string>FontAwesome5_Regular.ttf</string>
        <string>FontAwesome5_Solid.ttf</string>
        <string>FontAwesome6_Brands.ttf</string>
        <string>FontAwesome6_Regular.ttf</string>
        <string>FontAwesome6_Solid.ttf</string>
        <string>Foundation.ttf</string>
        <string>Ionicons.ttf</string>
        <string>MaterialIcons.ttf</string>
        <string>MaterialCommunityIcons.ttf</string>
        <string>SimpleLineIcons.ttf</string>
        <string>Octicons.ttf</string>
        <string>Zocial.ttf</string>
        <string>Fontisto.ttf</string>
    </array>
</dict>
</plist>


  • Set up for Android : Edit the android/app/build.gradle
  • Add apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle") at the end
android/app/build.gradle
android {
    ...
}

dependencies {
    ...
}

// Below should be added
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")

  • After above setup, iOS and Android project should be built again.
$ npx react-native run-ios
$ npx react-native run-android

  • Icons can be used like below example.
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';

export default function App() {
  return (
        <Icon name={'home'} size={50} color={MD3Colors.primary50}
          onPress={onIconPressed} />
	)
}


2. Making IconText component

  • Make following files in components directory.
$ cd src
$ cd components
$ touch IconText.tsx index.ts
$ cd ../..

  • Import TouchableView and use it in IconText component. Make IconText.tsx as below.
src/components/IconText.tsx
import React from 'react';
import type {FC, ComponentProps} from 'react';
import {Text} from 'react-native';
import type {TextStyle, StyleProp} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {TouchableView} from './TouchableView';
import type {TouchableViewProps} from './TouchableView';

export type IconTextProps = TouchableViewProps &
    ComponentProps<typeof Icon> & {
        text: number | string
        textStyle: StyleProp<TextStyle>
    }

export const IconText: FC<IconTextProps> = ({
    name, size, color, textStyle, text, ...touchableViewProps }) => {
        return (
            <TouchableView {...touchableViewProps}>
                <Icon name={name} size={size} color={color} />
                <Text style={textStyle}>{text}</Text>
            </TouchableView>
        )
    }

  • IconTextProps takes TouchableViewProps and custom props such as Icon and text, textStyle. text can be number or string.

  • To make it easy to use it in Person.tsx, make index.ts as below.
src/components/index.ts
export * from './TouchableView';
export * from './Avatar';
export * from './IconText';


3. Styling Person.tsx

  • Edit the structure with flexDirection and styling again the Person.tsx as below.
src/copy/Person.tsx
import React from 'react';
import type {FC} from 'react'; 
import {View, Text, Image, Alert} from 'react-native';
import {MD3Colors} from 'react-native-paper';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {styles} from './Person.style';
import * as D from '../data';
import moment from 'moment';
import {Avatar, IconText} from '../components';

export type PersonProps = {
    person: D.IPerson
}

const avatarPressed = () => Alert.alert('avatar pressed.')
const deletePressed = () => Alert.alert('delete pressed.')
const countIconPressed = (name: string) => () => Alert.alert(`${name} pressed`)

const Person: FC<PersonProps> = ({person}) => {
    return (
        <View style={[styles.view]}>
            <View style={[styles.leftView]}>
                <Avatar imageStyle={[styles.avatar]} uri={person.avatar} size={50}
                onPress={avatarPressed} />
            </View>
            <View style={[styles.rightView]}>
                <Text style={[styles.name]}>{person.name}</Text>
                <Text style={[styles.email]}>{person.email}</Text>
                <View style={[styles.dateView]}>
                    <Text style={[styles.text]}>
                        {moment(person.createdDate).startOf('day').fromNow()}
                    </Text>
                    <Icon name='trash-can' size={26} color={MD3Colors.secondary50}
                        onPress={deletePressed} />
                </View>
                <Text numberOfLines={3} ellipsizeMode="tail" style={[styles.text,
                    styles.comments]}>{person.comments}</Text>
                <Image style={[styles.image]} source={{uri: person.image}} />
                <View style={[styles.countsView]}>
                    <IconText ViewStyle={[styles.touchableIcon]}
                        onPress={countIconPressed('comment')}
                        name="comment" size={24} color={MD3Colors.secondary20}
                        textStyle={[styles.iconText]} text={person.counts.comment} />
                    <IconText ViewStyle={[styles.touchableIcon]}
                        onPress={countIconPressed('retweet')}
                        name="repeat-variant" size={24} color={MD3Colors.secondary20}
                        textStyle={[styles.iconText]} text={person.counts.retweet} />
                    <IconText ViewStyle={[styles.touchableIcon]}
                        onPress={countIconPressed('heart')}
                        name="heart" size={24} color={MD3Colors.secondary20}
                        textStyle={[styles.iconText]} text={person.counts.heart} />
                </View>
            </View>
        </View>
    )
}
export default Person
  • To limit the text, use the numberOfLines attribute. In this case numberOfLines={3} is used.
  • With ellipsizeMode="tail" attribute, it shows "..." at the end of text when there is more text behind 3rd line.
  • Icon name such as trash-can, comment etc is found in here: https://pictogrammers.com/library/mdi/


src/copy/Person.style.ts
import {StyleSheet} from 'react-native';
import {MD3Colors} from 'react-native-paper';

export const styles = StyleSheet.create({
  view: {
    flexDirection: 'row',
    backgroundColor: MD3Colors.primary80,
    padding: 5,
  },
  leftView: {padding: 5},
  avatar: {borderColor: MD3Colors.primary100, borderWidth: 2},
  rightView: {flex: 1, padding: 5, marginRight: 10},
  name: {marginRight: 5, fontSize: 22, fontWeight: '500'},
  email: {
    textDecorationLine: 'underline',
    color: MD3Colors.secondary100,
    textDecorationColor: MD3Colors.secondary80,
  },
  dateView: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    padding: 3,
    marginTop: 5,
  },
  text: {fontSize: 16},
  comments: {marginTop: 10, fontSize: 16},
  image: {height: 150, marginTop: 15},
  countsView: {
    flexDirection: 'row',
    padding: 3,
    justifyContent: 'space-around',
  },
  touchableIcon: {flexDirection: 'column', padding: 5, alignItems: 'center'},
  iconText: {color: MD3Colors.primary200, marginLeft: 3},
});
  • Align the view with leftView and rightView. In the leftView there is only avatar icon, and in the rightView there are other contents just like Insta.
  • At the bottom of the rightView, there are comment, retweet, heart in a row. flexDirection row and space-around so it looks more familiar.

  • When this is rendered in simulator, it will look like as below.



Comments

Mostly viewed post

Web-app dev4, Google AdMob (Banner and Interstitial ads)

Web-app dev1, Web development and robots.txt