Show Timeline using React Native Timeline ListView

React Native Timeline ListView

This is an Example to Show Timeline using React Native Timeline ListView in Android and IOS. Timeline is very useful to show event activity or progress. The timeline list can be used in many places. For this example, we have used Timeline component provided by react-native-timeline-flatlist.

As ListView has been deprecated in React Native 0.60+ we have updated this example for the FlatList. Enjoy 🙂

If we think about the practical use of Timeline then the best example which comes in my mind is the delivery process of any product from online purchase to doorstep delivery. Other than that you can also use Timeline to make a School event calendar or any function calendar with dates and time. Ther can be many more places where we can use Timeline. If you want to share some more places where we can use Timeline then comment below to help other readers.

Now coming back to the example. In this example, we are making a view with buttons in a horizontal scroll view on top and the main view which will hold the different types of Timeline components. On the click of the top buttons, we will change the component in the main area. It is kind of an Activity holding different fragments for those who have no idea about the last line don’t worry you can visit How to Make a View Like Android Fragment in React Native to have an idea about that.

Types of Timeline ListView

The post contains the following Timeline ListView

  1. Basic TimeLine.
  2. Custom TimeLine.
  3. Dot TimeLine.
  4. Icon TimeLine.
  5. Override Render TimeLine.
  6. Refresh and Load More data in TimeLine.
  7. Right  Side Single TimeLine.
  8. Template TimeLine.
  9. Capture onPress on the TimeLine.
  10. Two Column TimeLine.

So let’s start with the example.

To Make a React Native App

Getting started with React Native will help you to know more about the way you can make a React Native project. We are going to use react-native init to make our React Native App. Assuming that you have node installed, you can use npm to install the react-native-cli command line utility. Open the terminal and go to the workspace and run

npm install -g react-native-cli

Run the following commands to create a new React Native project

react-native init ProjectName

If you want to start a new project with a specific React Native version, you can use the --version argument:

react-native init ProjectName --version X.XX.X
react-native init ProjectName --version react-native@next

This will make a project structure with an index file named App.js in your project directory.

Installation of Dependency

To use Timeline we need to install react-native-timeline-flatlist dependency.

To install this open the terminal and jump into your project using

cd ProjectName

Run the following command to install

npm install react-native-timeline-flatlist --save

This command will copy all the dependency into your node_module directory. –save is optional, it is just to update the react-native-timeline-flatlist dependency in your package.json file.

As the example has 10 different screens and is very long I am making an App.js which will be the main screen and other screens are like independent components so I’ll post the code and then a screenshot of it. If you are facing any issue with that then you can comment below so that I can update the post accordingly.

Project Structure

For this project, you have to create a project structure as shown below. You can also download the files from here.

Code for Timeline ListView

App.js

This will be our main landing screen which has some buttons on the top in the horizontal scroll view. On pressing the buttons, we are returning different views to show.

/*React Native TimeLine ListView / Flatlist*/
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
import BasicTimeLine from './components/BasicTimeLine';
import CustomTimeLine from './components/CustomTimeLine';
import DotTimeLine from './components/DotTimeLine';
import IconTimeLine from './components/IconTimeLine';
import OverrideRenderTimeLine from './components/OverrideRenderTimeLine';
import RefreshLoadMoreTimeLine from './components/RefreshLoadMoreTimeLine';
import SingleRightTimeLine from './components/SingleRightTimeLine';
import TemplateTimeLine from './components/TemplateTimeLine';
import TimeLinePress from './components/TimeLinePress';
import TwoColumnTimeLine from './components/TwoColumnTimeLine';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    //state to manage the screen visible at a time
    this.state = { val: 1 };
  }
  renderElement() {
    //You can add N number of Views here in if-else condition
    if (this.state.val === 1) {
      return <BasicTimeLine />;
    } else if (this.state.val === 2) {
      return <CustomTimeLine />;
    } else if (this.state.val === 3) {
      return <DotTimeLine />;
    } else if (this.state.val === 4) {
      return <IconTimeLine />;
    } else if (this.state.val === 5) {
      return <OverrideRenderTimeLine />;
    } else if (this.state.val === 6) {
      return <RefreshLoadMoreTimeLine />;
    } else if (this.state.val === 7) {
      return <SingleRightTimeLine />;
    } else if (this.state.val === 8) {
      return <TemplateTimeLine />;
    } else if (this.state.val === 9) {
      return <TimeLinePress />;
    } else if (this.state.val === 10) {
      return <TwoColumnTimeLine />;
    }
  }
  render() {
    return (
      <View style={styles.container}>
        <View>
          <ScrollView horizontal>
            <View style={{ flexDirection: 'row' }}>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 1 })}>
                <Text style={{ color: '#ffffff' }}>Basic TimeLine</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 2 })}>
                <Text style={{ color: '#ffffff' }}>Custom TimeLine</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 3 })}>
                <Text style={{ color: '#ffffff' }}>Dot TimeLine</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 4 })}>
                <Text style={{ color: '#ffffff' }}>Icon TimeLine</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 5 })}>
                <Text style={{ color: '#ffffff' }}>
                  Override Render TimeLine
                </Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 6 })}>
                <Text style={{ color: '#ffffff' }}>
                  Refresh Load More TimeLine
                </Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 7 })}>
                <Text style={{ color: '#ffffff' }}>Single Right TimeLine</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 8 })}>
                <Text style={{ color: '#ffffff' }}>Template TimeLine</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 9 })}>
                <Text style={{ color: '#ffffff' }}>TimeLine Press</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.button}
                onPress={() => this.setState({ val: 10 })}>
                <Text style={{ color: '#ffffff' }}>Two Column TimeLine</Text>
              </TouchableOpacity>
            </View>
          </ScrollView>
        </View>

        {/*View to hold the child screens 
        which can be changed on the click of a button*/}
        <View style={{ backgroundColor: '#f9f9f9', flex: 1 }}>
          {this.renderElement()}
        </View>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#ffffff',
    padding: 8,
    marginTop: 30,
  },
  button: {
    flex: 1,
    alignItems: 'center',
    backgroundColor: '#808080',
    padding: 10,
    margin: 2,
  },
});

After creating the main screen now you can see the screenshot and the code for different Timeline.

BasicTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class BasicTimeLine extends Component {
  constructor() {
    super();
    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      },
      {
        time: '12:00',
        title: 'Event 3',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s.',
      },
      {
        time: '14:00',
        title: 'Event 4',
        description:
          'It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s.',
      },
      {
        time: '16:30',
        title: 'Event 5',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
      },
    ];
  }

  render() {
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Basic TimeLine Example
        </Text>
        <Timeline style={{ flex: 1 }} data={this.data} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: 'white',
  },
});

CustomTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class CustomTimeLine extends Component {
  constructor() {
    super();
    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
        circleColor: '#009688',
        lineColor: '#009688',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      },
      { time: '12:00', title: 'Event 2' },
      {
        time: '14:00',
        title: 'Event 3',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry. ',
        lineColor: '#009688',
      },
      {
        time: '16:30',
        title: 'Event 4',
        description:
          'It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
        circleColor: '#009688',
      },
    ];
  }

  render() {
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Custom TimeLine Example
        </Text>
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgb(45,156,219)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
});

DotTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class DotTimeLine extends Component {
  constructor() {
    super();
    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
        circleColor: '#009688',
        lineColor: '#009688',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      },
      {
        time: '14:00',
        title: 'Event 4',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
        lineColor: '#009688',
      },
      {
        time: '16:30',
        title: 'Event 5',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
        circleColor: '#009688',
      },
    ];
  }

  render() {
    //'rgb(45,156,219)'
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Dot TimeLine Example
        </Text>
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgb(45,156,219)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
          innerCircle={'dot'}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
  },
});

IconTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class IconTimeLine extends Component {
  constructor() {
    super();
    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
        icon: require('../img/place_holder.png'),
      },
      { time: '12:00', title: 'Lunch', icon: require('../img/place_holder.png') },
      {
        time: '14:00',
        title: 'Event 3',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '16:30',
        title: 'Event 4',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
        icon: require('../img/place_holder.png'),
      },
    ];
  }

  render() {
    //'rgb(45,156,219)'
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Icon TimeLine Example
        </Text>
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgba(0,0,0,0)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
          innerCircle={'icon'}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
});

OverrideRenderTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class OverrideRenderTimeLine extends Component {
  constructor() {
    super();
    this.onEventPress = this.onEventPress.bind(this);
    this.renderSelected = this.renderSelected.bind(this);
    this.renderDetail = this.renderDetail.bind(this);

    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '12:00',
        title: 'Event 3',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '14:00',
        title: 'Event 4',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '16:30',
        title: 'Event 5',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
    ];
    this.state = { selected: null };
  }

  onEventPress(data) {
    this.setState({ selected: data });
  }

  renderSelected() {
    if (this.state.selected)
      return (
        <Text style={{ marginTop: 10 }}>
          Selected event: {this.state.selected.title} at{' '}
          {this.state.selected.time}
        </Text>
      );
  }

  renderDetail(rowData, sectionID, rowID) {
    let title = <Text style={[styles.title]}>{rowData.title}</Text>;
    var desc = null;
    if (rowData.description && rowData.imageUrl)
      desc = (
        <View style={styles.descriptionContainer}>
          <Image source={{ uri: rowData.imageUrl }} style={styles.image} />
          <Text style={[styles.textDescription]}>{rowData.description}</Text>
        </View>
      );

    return (
      <View style={{ flex: 1 }}>
        {title}
        {desc}
      </View>
    );
  }

  render() {
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Override Render TimeLine Example
        </Text>
        {this.renderSelected()}
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgba(0,0,0,0)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
          innerCircle={'icon'}
          onEventPress={this.onEventPress}
          renderDetail={this.renderDetail}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
  title: {
    fontSize: 16,
    fontWeight: 'bold',
  },
  descriptionContainer: {
    flexDirection: 'row',
    paddingRight: 50,
  },
  image: {
    width: 50,
    height: 50,
    borderRadius: 25,
  },
  textDescription: {
    marginLeft: 10,
    color: 'gray',
  },
});

RefreshLoadMoreTimeLine.js

  
/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  RefreshControl,
  ActivityIndicator,
} from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class RefreshLoadMoreTimeLine extends Component {
  constructor() {
    super();
    this.onEndReached = this.onEndReached.bind(this);
    this.renderFooter = this.renderFooter.bind(this);
    this.onRefresh = this.onRefresh.bind(this);

    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      },
      { time: '12:00', title: 'Lunch', icon: require('../img/place_holder.png') },
      {
        time: '14:00',
        title: 'Event 3',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
      },
      {
        time: '16:30',
        title: 'Event 4',
        description:
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      },
    ];

    this.state = {
      isRefreshing: false,
      waiting: false,
      data: this.data,
    };
  }

  onRefresh() {
    this.setState({ isRefreshing: true });
    //refresh to initial data
    setTimeout(() => {
      //refresh to initial data
      this.setState({
        data: this.data,
        isRefreshing: false,
      });
    }, 2000);
  }

  onEndReached() {
    if (!this.state.waiting) {
      this.setState({ waiting: true });

      //fetch and concat data
      setTimeout(() => {
        //refresh to initial data
        var data = this.state.data.concat([
          {
            time: '18:00',
            title: 'More Loaded Event 5',
            description:
              'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
          },
          {
            time: '18:00',
            title: 'More Loaded Event 6',
            description:
              'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum.',
          },
          {
            time: '18:00',
            title: 'More Loaded Event 7',
            description:
              'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry.',
          },
          {
            time: '18:00',
            title: 'More Loaded Event 8',
            description:
              'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
          },
          {
            time: '18:00',
            title: 'More Loaded Event 9',
            description:
              'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
          },
        ]);

        this.setState({
          waiting: false,
          data: data,
        });
      }, 2000);
    }
  }

  renderFooter() {
    if (this.state.waiting) {
      return <ActivityIndicator />;
    } else {
      return <Text>~</Text>;
    }
  }

  render() {
    //'rgb(45,156,219)'
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Refresh Load More Example
        </Text>
        <Timeline
          style={styles.list}
          data={this.state.data}
          circleSize={20}
          circleColor="rgb(45,156,219)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
            refreshControl: (
              <RefreshControl
                refreshing={this.state.isRefreshing}
                onRefresh={this.onRefresh}
              />
            ),
            renderFooter: this.renderFooter,
            onEndReached: this.onEndReached,
          }}
          innerCircle={'dot'}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
});

SingleRightTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class SingleRightTimeLine extends Component {
  constructor() {
    super();
    this.onEventPress = this.onEventPress.bind(this);
    this.renderSelected = this.renderSelected.bind(this);
    this.renderDetail = this.renderDetail.bind(this);

    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages.',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '12:00',
        title: 'Event 3',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '14:00',
        title: 'Event 4',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '16:30',
        title: 'Event 5',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
    ];
    this.state = { selected: null };
  }

  onEventPress(data) {
    this.setState({ selected: data });
  }

  renderSelected() {
    if (this.state.selected)
      return (
        <Text style={{ marginTop: 10 }}>
          Selected event: {this.state.selected.title} at{' '}
          {this.state.selected.time}
        </Text>
      );
  }

  renderDetail(rowData, sectionID, rowID) {
    let title = <Text style={[styles.title]}>{rowData.title}</Text>;
    var desc = null;
    if (rowData.description && rowData.imageUrl)
      desc = (
        <View style={styles.descriptionContainer}>
          <Image source={{ uri: rowData.imageUrl }} style={styles.image} />
          <Text style={[styles.textDescription]}>{rowData.description}</Text>
        </View>
      );

    return (
      <View style={{ flex: 1 }}>
        {title}
        {desc}
      </View>
    );
  }

  render() {
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Right Side Single TImeline Example
        </Text>
        {this.renderSelected()}
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgba(0,0,0,0)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
          innerCircle={'icon'}
          onEventPress={this.onEventPress}
          renderDetail={this.renderDetail}
          separator={false}
          detailContainerStyle={{
            marginBottom: 20,
            paddingLeft: 5,
            paddingRight: 5,
            backgroundColor: '#BBDAFF',
            borderRadius: 10,
          }}
          columnFormat="single-column-right"
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
  title: {
    fontSize: 16,
    fontWeight: 'bold',
  },
  descriptionContainer: {
    flexDirection: 'row',
    paddingRight: 50,
  },
  image: {
    width: 50,
    height: 50,
    borderRadius: 25,
  },
  textDescription: {
    marginLeft: 10,
    color: 'gray',
  },
});

TemplateTimeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class TemplateTimeLine extends Component {
  constructor() {
    super();
    this.data = [
      {
        time: '09:00',
        title: 'Archery Training',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages.',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently.',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '12:00',
        title: 'Event 3',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages.',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '14:00',
        title: 'Event 4',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '16:30',
        title: 'Event 5',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages.',
        icon: require('../img/place_holder.png'),
      },
    ];
  }

  render() {
    //'rgb(45,156,219)'
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Template TImeline Example
        </Text>
        <Timeline
          style={styles.list}
          data={this.data}
          //separator={true}
          circleSize={20}
          circleColor="rgba(0,0,0,0)"
          //circleStyle={{borderWidth:1}}
          //dotColor='yellow'
          //lineWidth={2}
          //lineColor='rgb(45,156,219)'
          //timeTextStyle={{color:'green'}}
          //timeContainerStyle={{minWidth: 65}}
          //titleStyle={{color:'green'}}
          //descriptionStyle={{color:'red'}}
          innerCircle={'icon'}
          //iconStyle={{backgroundColor:'white'}}
          //separatorStyle={{backgroundColor: 'green'}}
          //scrollEnabled={false}
          options={{}}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
});

TimeLinePress.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class TimeLinePress extends Component {
  constructor() {
    super();
    this.onEventPress = this.onEventPress.bind(this);
    this.renderSelected = this.renderSelected.bind(this);
    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.',
        icon: require('../img/place_holder.png'),
      },
      { time: '12:00', title: 'Lunch', icon: require('../img/place_holder.png') },
      {
        time: '14:00',
        title: 'Event 3',
        description:
          'Lorem Ipsum has been the industrys standard dummy text ever since the 1500s.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '16:30',
        title: 'Event 4',
        description:
          'Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.',
        icon: require('../img/place_holder.png'),
      },
    ];
    this.state = { selected: null };
  }

  onEventPress(data) {
    this.setState({ selected: data });
  }

  renderSelected() {
    if (this.state.selected)
      return (
        <Text style={{ marginTop: 10 }}>
          Selected event: {this.state.selected.title} at{' '}
          {this.state.selected.time}
        </Text>
      );
  }

  render() {
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          TImeline Press Example
        </Text>
        {this.renderSelected()}
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgba(0,0,0,0)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
          innerCircle={'icon'}
          onEventPress={this.onEventPress}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
});

TwoColumnTmeLine.js

/*React Native TimeLine ListView / Flatlist*/
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import Timeline from 'react-native-timeline-flatlist';

export default class TwoColumnTmeLine extends Component {
  constructor() {
    super();
    this.onEventPress = this.onEventPress.bind(this);
    this.renderSelected = this.renderSelected.bind(this);

    this.data = [
      {
        time: '09:00',
        title: 'Event 1',
        description:
          'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '10:45',
        title: 'Event 2',
        description:
          'It is a long established fact that a reader will be distracted by the readable content.',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '12:00',
        title: 'Event 3',
        icon: require('../img/place_holder.png'),
      },
      {
        time: '14:00',
        title: 'Event 4',
        description:
          'It is a long established fact that a reader will be distracted by the readable content of a page when looking.',
        lineColor: '#009688',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
      {
        time: '16:30',
        title: 'Event 5',
        description:
          'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.',
        icon: require('../img/place_holder.png'),
        imageUrl:
          'https://images.pexels.com/photos/2250394/pexels-photo-2250394.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=250&w=250',
      },
    ];
    this.state = { selected: null };
  }

  onEventPress(data) {
    this.setState({ selected: data });
  }

  renderSelected() {
    if (this.state.selected)
      return (
        <Text style={{ marginTop: 10 }}>
          Selected event: {this.state.selected.title} at{' '}
          {this.state.selected.time}
        </Text>
      );
  }

  render() {
    return (
      <View style={styles.container}>
        <Text
          style={{
            padding: 16,
            fontSize: 20,
            textAlign: 'center',
            fontWeight: 'bold',
          }}>
          Two Column TimeLine Example
        </Text>
        {this.renderSelected()}
        <Timeline
          style={styles.list}
          data={this.data}
          circleSize={20}
          circleColor="rgba(0,0,0,0)"
          lineColor="rgb(45,156,219)"
          timeContainerStyle={{ minWidth: 52, marginTop: -5 }}
          timeStyle={{
            textAlign: 'center',
            backgroundColor: '#ff9797',
            color: 'white',
            padding: 5,
            borderRadius: 13,
          }}
          descriptionStyle={{ color: 'gray' }}
          options={{
            style: { paddingTop: 5 },
          }}
          innerCircle={'icon'}
          onEventPress={this.onEventPress}
          separator={false}
          detailContainerStyle={{
            marginBottom: 20,
            paddingLeft: 5,
            paddingRight: 5,
            backgroundColor: '#BBDAFF',
            borderRadius: 10,
          }}
          columnFormat="two-column"
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: 'white',
  },
  list: {
    flex: 1,
    marginTop: 20,
  },
});

To Run the React Native App

Open the terminal again and jump into your project using.
cd ProjectName
To run the project on an Android Virtual Device or on real debugging device
react-native run-android
or on the iOS Simulator by running
react-native run-ios (macOS only).

Output Screenshots

               .   .   .   .  

Output in Online Emulator


This is how you can show Timeline using React Native Timeline ListView / Flat list in Android and IOS. If you have any doubts or you want to share something about the topic you can comment below or contact us here. There will be more posts coming soon. Stay tuned!

Hope you liked it. 🙂


Related Posts

10 thoughts on “Show Timeline using React Native Timeline ListView”

    • Hello Ayodele,
      They do not provide that much customization. So if you want to add those things you have to create your own.
      Can you please clarify what you want. maybe I can help you to make your own component.

      Reply
  1. [13:05:51] E | ReactNativeJS ▶︎ ListView has been removed from React Native. See https://fb.me/nolistview for more information or use `deprecated-react-native-listview`.

    [13:05:52] E | ReactNativeJS ▶︎ Module AppRegistry is not a registered callable module (calling runApplication)

    show this err sir

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.