Flutter Timeline Tile Example

Timeline tile in Flutter is used to show progression of a given task to the user. It shows the level of completion of a task with the completed and incomplete steps for a certain event.

In today’s applications, timeline tile is widely used and plays a significant role in improving user friendliness and user’s experience.

Timeline tile is used in various scenarios. For example,  delivery applications, multi-steps forms, and progress tracking. In other words, it’s used to show users the starting point, milestones, and ending point in a highly visual and easy tracking format.

Furthermore, it illustrate sequence of required steps in a very effective and attractive way. So, it acts as a roadmap to display a chain of activities or events that the user needs to complete to achieve a certain goal.

Now, Timeline tile can be displayed in both horizontal and vertical direction. Moreover, It’s very easy to implement and highly customizable.

In this tutorial, we’ll go through a complete flutter Timeline tile example using timeline_tile package.

So, without further ado, let’s start our tutorial!

Table of Contents

  1. Setting up Flutter project
  2. Timeline Tile  Constructor
  3. Timeline Tile properties
  4. Delivery Timeline Example
    1. Creating the first timeline tile
    2. Creating the second timeline tile
    3. Implementing the third timeline tile
    4. Adding floating action button
    5. Complete Code
  5. Success Steps Timeline Tile Example
    1. Creating the first timeline tile
    2. Creating the Timeline divider
    3. Complete Code
  6. Conclusion

Setting up Flutter project

Firstly , create a new Flutter project then open pubspec.yaml file to add timeline_tile dependency then click Pub get.

timeline_tile: ^2.0.0

Then, create a new dart file and import the following library

import 'package:timeline_tile/timeline_tile.dart';

Timeline Tile Constructor

const TimelineTile({
  Key? key,
  this.axis = TimelineAxis.vertical,
  this.alignment = TimelineAlign.start,
  this.startChild,
  this.endChild,
  this.lineXY,
  this.hasIndicator = true,
  this.isFirst = false,
  this.isLast = false,
  this.indicatorStyle = const IndicatorStyle(width: 25),
  this.beforeLineStyle = const LineStyle(),
  LineStyle? afterLineStyle,
})

Timeline Tile properties

PropertyDescription
axisdefines the direction of the timeline tile to be horizontal or vertical. By default, Timeline tile is set to horizontal direction.
alignmentspecifies the tile alignment. By default, it’s set to TimelineTileAlign.Start. It has 4 values which are start, end, center, and manual. Manual alignment is used to manually align the timeline tile.
startChildthe widget that takes place before the timeline tile
endChildthe widget that takes place after the timeline tile
hasIndicatorspecifies whether the tile has an indicator or not. By default, hasIndicator is set to true
indicatorStylecustomizes the appearance of the tile’s indicator including its color, width, height, and icon.
lineXYdefines the position of the timeline in case of manual alignment. It takes values between 0 and 1.
isFirstspecifies if the tile is the first tile of the sequence. If set to true, the tile will not have a line before the indicator
isLastspecifies if the tile is the last tile of the sequence. If set to true, the tile will not have a line after the indicator
beforeLineStylecustomizes the line before the tile’s indicator such as the thickness and color.
afterLineStylecustomizes the line after the tile’s indicator such as the thickness and color.

Delivery Timeline Example

In this example, we’ll create a timeline to show progress indicator of food order. It shows a sequence of order status that help the user track their order easily.

We’ll be creating 3 tiles to show the progress of order receiving, processing and delivering. In addition, we’ll use the floating action button to illustrate the progression and how the tile’s icon and color change accordingly.

Now, before we create the first tile, let’s creating an integer value index that will be responsible for controlling the changes in tiles appearance when the progress changes.

int index = 0;

Creating the first timeline tile

TimelineTile(
axis: TimelineAxis.vertical,
indicatorStyle: IndicatorStyle(
color: index == 0 ? Colors.pink : Colors.pink.shade200,
height: 40,
width: 40,
iconStyle: IconStyle(
color: Colors.white,
iconData: index ==0 ? Icons.emoji_emotions_outlined :Icons.check,
),


),
isFirst: true,
afterLineStyle: LineStyle(
color: index > 0 ? Colors.green : Colors.grey
),

alignment: TimelineAlign.start,
endChild: Row(

children: [
SizedBox(width: 30,),
Container(

margin: EdgeInsets.only(top: 10,bottom:30),
height: 80,
width: 280,
decoration: BoxDecoration(
boxShadow:
[
BoxShadow(
blurRadius: 6,
color: Colors.grey
),
],

//borderRadius: BorderRadius.all(Radius.circular(24)),
border: Border(
top: BorderSide(
color: Colors.pink,
width: 5
)
),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Text('Ordered Received', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),

Padding(
padding: EdgeInsets.all(8.0),
child: Text('We\'ve received your order', style: TextStyle(fontSize: 16),),
)
],
),
),
],
),

),
flutter timeline tile example

Creating the second timeline tile

TimelineTile(
axis: TimelineAxis.vertical,
indicatorStyle: IndicatorStyle(
color: index == 1 ? Colors.pink : Colors.pink.shade200,
height: 40,
width: 40,
iconStyle: IconStyle(
color: Colors.white,
iconData: index == 1 ? Icons.fastfood_rounded :Icons.check,
),


),
beforeLineStyle: LineStyle(
color: index > 0 ? Colors.green : Colors.grey
),
afterLineStyle: LineStyle(
color: index > 1 ? Colors.green : Colors.grey
),

alignment: TimelineAlign.start,
endChild: Row(

children: [
SizedBox(width: 30,),
Container(
margin: EdgeInsets.only(top: 10,bottom:30),
height: 80,
width: 280,
decoration: BoxDecoration(
boxShadow:
[
BoxShadow(
blurRadius: 6,
color: Colors.grey
),
],
border: Border(
top: BorderSide(
color: Colors.pink,
width: 5
)
),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Text('Order in Process', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),

Padding(
padding: EdgeInsets.all(8.0),
child: Text('Your order is being prepared', style: TextStyle(fontSize: 16),),
)


],
),
),
],
),

),
flutter timeline tile example

Implementing the third timeline tile

TimelineTile(
axis: TimelineAxis.vertical,
indicatorStyle: IndicatorStyle(
color: index == 2 ? Colors.pink : Colors.pink.shade200,
height: 40,
width: 40,
iconStyle: IconStyle(
color: Colors.white,
iconData: index == 2 ? Icons.delivery_dining_outlined :Icons.check,
),


),
isLast: true,
beforeLineStyle: LineStyle(
color: index > 1 ? Colors.green : Colors.grey,
),

alignment: TimelineAlign.start,
endChild: Row(

children: [
SizedBox(width: 30,),
Container(

margin: EdgeInsets.only(top: 10,bottom:30),
height: 80,
width: 280,
decoration: BoxDecoration(
boxShadow:
[
BoxShadow(
blurRadius: 6,
color: Colors.grey
),
],
border: Border(
top: BorderSide(
color: Colors.pink,
width: 5
)
),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Text('Order in Delivery', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),

Padding(
padding: EdgeInsets.all(8.0),
child: Text('Your order is on its way to you!', style: TextStyle(fontSize: 16),),
)


],
),
),
],
),

),
flutter timeline tile example

Adding floating action button

floatingActionButton: FloatingActionButton(
onPressed: () {
//increase
setState(() {
index +=1;
});
},
child: Icon(
index < 3 ? Icons.navigate_next : Icons.done ),
),
flutter timeline tile example

Complete Code

int index = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
title: Text('Flutter Timeline Tile Example'),
centerTitle: true,
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(left: 8, right: 8),
child: Column(
children: [
TimelineTile(
axis: TimelineAxis.vertical,
indicatorStyle: IndicatorStyle(
color: index == 0 ? Colors.pink : Colors.pink.shade200,
height: 40,
width: 40,
iconStyle: IconStyle(
color: Colors.white,
iconData: index ==0 ? Icons.emoji_emotions_outlined :Icons.check,
),


),
isFirst: true,
afterLineStyle: LineStyle(
color: index > 0 ? Colors.green : Colors.grey
),

alignment: TimelineAlign.start,
endChild: Row(

children: [
SizedBox(width: 30,),
Container(

margin: EdgeInsets.only(top: 10,bottom:30),
height: 80,
width: 280,
decoration: BoxDecoration(
boxShadow:
[
BoxShadow(
blurRadius: 6,
color: Colors.grey
),
],

//borderRadius: BorderRadius.all(Radius.circular(24)),
border: Border(
top: BorderSide(
color: Colors.pink,
width: 5
)
),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Text('Ordered Received', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),

Padding(
padding: EdgeInsets.all(8.0),
child: Text('We\'ve received your order', style: TextStyle(fontSize: 16),),
)


],
),
),
],
),

),
TimelineTile(
axis: TimelineAxis.vertical,
indicatorStyle: IndicatorStyle(
color: index == 1 ? Colors.pink : Colors.pink.shade200,
height: 40,
width: 40,
iconStyle: IconStyle(
color: Colors.white,
iconData: index == 1 ? Icons.fastfood_rounded :Icons.check,
),


),
beforeLineStyle: LineStyle(
color: index > 0 ? Colors.green : Colors.grey
),
afterLineStyle: LineStyle(
color: index > 1 ? Colors.green : Colors.grey
),

alignment: TimelineAlign.start,
endChild: Row(

children: [
SizedBox(width: 30,),
Container(
margin: EdgeInsets.only(top: 10,bottom:30),
height: 80,
width: 280,
decoration: BoxDecoration(
boxShadow:
[
BoxShadow(
blurRadius: 6,
color: Colors.grey
),
],
border: Border(
top: BorderSide(
color: Colors.pink,
width: 5
)
),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Text('Order in Process', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),

Padding(
padding: EdgeInsets.all(8.0),
child: Text('Your order is being prepared', style: TextStyle(fontSize: 16),),
)


],
),
),
],
),

),
TimelineTile(
axis: TimelineAxis.vertical,
indicatorStyle: IndicatorStyle(
color: index == 2 ? Colors.pink : Colors.pink.shade200,
height: 40,
width: 40,
iconStyle: IconStyle(
color: Colors.white,
iconData: index == 2 ? Icons.delivery_dining_outlined :Icons.check,
),


),
isLast: true,
beforeLineStyle: LineStyle(
color: index > 1 ? Colors.green : Colors.grey,
),

alignment: TimelineAlign.start,
endChild: Row(

children: [
SizedBox(width: 30,),
Container(

margin: EdgeInsets.only(top: 10,bottom:30),
height: 80,
width: 280,
decoration: BoxDecoration(
boxShadow:
[
BoxShadow(
blurRadius: 6,
color: Colors.grey
),
],
border: Border(
top: BorderSide(
color: Colors.pink,
width: 5
)
),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Text('Order in Delivery', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
),

Padding(
padding: EdgeInsets.all(8.0),
child: Text('Your order is on its way to you!', style: TextStyle(fontSize: 16),),
)


],
),
),
],
),

),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
//increase
setState(() {
index +=1;
});
},
child: Icon(
index < 3 ? Icons.navigate_next : Icons.done ),
),

);
}
flutter timeline tile example

Success Steps Timeline Tile Example

Besides using timeline to show progress of events, we can use it to create a story timeline to deliver the user a specific message. In this example, we’ll create a timeline in a different appearance by combining Timeline Tile and Timeline Divider. In this example, we’ll manually position the tiles and dividers to show the user 5 steps for success. Now, timeline divider is used to display a horizontal or vertical line to separate the timeline tiles and enhance the appearance of timeline.

Creating the first timeline tile

TimelineTile(
axis: TimelineAxis.vertical,
alignment: TimelineAlign.manual,
lineXY: 0.1,
isFirst: true,

indicatorStyle: IndicatorStyle(
width: 40,
height:40,
indicator: Container(
width: 50,
height: 50,
child: Center(child: Text('1', style: TextStyle(fontSize: 26, color: Colors.white, fontFamily: 'Dancing Script'),)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.pink
),
)
),
afterLineStyle: LineStyle(color: Colors.pink),
endChild: Container(
margin: EdgeInsets.only(top: 20, left: 40, right: 10, bottom: 10),
width: 200,
height: 140,

child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('Believe in yourself!', textAlign: TextAlign.right, style: TextStyle(color: Colors.pink, fontWeight: FontWeight.bold, fontSize: 24),),
SizedBox(height: 10),
Text('belive that you can achieve your dreams'
' when you want to do so. Trust that you cando any thing you set your mind to',textAlign: TextAlign.right, style: TextStyle(color: Colors.pink[500], fontSize: 20),)
],
),
),
),
flutter timeline tile example

Creating the Timeline divider

TimelineDivider(
thickness: 4,
begin: 0.1,
end: 0.9,
color: Colors.pink,
axis: TimelineAxis.horizontal,
),
flutter timeline tile example

Complete Code

Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
title: Text('Flutter Timeline Tile Example'),
centerTitle: true,
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(left: 8, right: 8),
child: Column(

children: [

Container(
width: MediaQuery.of(context).size.width,
height: 70,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.pink.withOpacity(0.2)
),
margin: EdgeInsets.only(top: 20, left: 10, right: 10),
padding: EdgeInsets.only(left: 10, right: 10),
child: Center(
child: Text(
'5 Steps to be successful',
style: TextStyle(
fontSize: 30,
color: Colors.pink
),
),
),
),
//1
TimelineTile(
axis: TimelineAxis.vertical,
alignment: TimelineAlign.manual,
lineXY: 0.1,
isFirst: true,

indicatorStyle: IndicatorStyle(
width: 40,
height:40,
indicator: Container(
width: 50,
height: 50,
child: Center(child: Text('1', style: TextStyle(fontSize: 26, color: Colors.white, fontFamily: 'Dancing Script'),)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.pink
),
)
),
afterLineStyle: LineStyle(color: Colors.pink),
endChild: Container(
margin: EdgeInsets.only(top: 20, left: 40, right: 10, bottom: 10),
width: 200,
height: 140,

child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('Believe in yourself!', textAlign: TextAlign.right, style: TextStyle(color: Colors.pink, fontWeight: FontWeight.bold, fontSize: 24),),
SizedBox(height: 10),
Text('belive that you can achieve your dreams'
' when you want to do so. Trust that you cando any thing you set your mind to',textAlign: TextAlign.right, style: TextStyle(color: Colors.pink[500], fontSize: 20),)
],
),
),
),

TimelineDivider(
thickness: 4,
begin: 0.1,
end: 0.9,
color: Colors.pink,
axis: TimelineAxis.horizontal,
),
//2
TimelineTile(
axis: TimelineAxis.vertical,
alignment: TimelineAlign.manual,
lineXY: 0.9,
beforeLineStyle: LineStyle(color: Colors.pink),
afterLineStyle: LineStyle(color: Colors.pink),
indicatorStyle: IndicatorStyle(
width: 40,
height:40,
indicator: Container(
width: 50,
height: 50,
child: Center(child: Text('2', style: TextStyle(fontSize: 26, color: Colors.white, fontFamily: 'Dancing Script'),)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.pink
),
)
),
startChild: Container(
width: 50,
height: 140,
margin: EdgeInsets.only(top: 30, bottom: 10, left: 10, right: 40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Work Hard!', textAlign: TextAlign.left, style: TextStyle(color: Colors.pink, fontWeight: FontWeight.bold, fontSize: 24),),
SizedBox(height: 10),
Text('don\'t stop when you\'re tired, stop when you\'re done! \ndo whatever it takes no matter how hard it is',textAlign: TextAlign.left, style: TextStyle(color: Colors.pink[500], fontSize: 20),)
],
),
),
),
TimelineDivider(
axis: TimelineAxis.horizontal,
thickness: 4,
color: Colors.pink,
begin: 0.055,
end: 0.9,
),

//3
TimelineTile(
axis: TimelineAxis.vertical,
alignment: TimelineAlign.manual,
lineXY: 0.01,
indicatorStyle: IndicatorStyle(
width: 40,
height:40,
indicator: Container(
width: 50,
height: 50,
child: Center(child: Text('3', style: TextStyle(fontSize: 26, color: Colors.white, fontFamily: 'Dancing Script'),)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.pink
),
)
),
beforeLineStyle: LineStyle(color: Colors.pink),
endChild: Container(
width: 50,
height: 140,
margin: EdgeInsets.only(top: 20, bottom: 20, left: 50, right: 10),

child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('Set measurable goals!', textAlign: TextAlign.right, style: TextStyle(color: Colors.pink, fontWeight: FontWeight.bold, fontSize: 24),),
SizedBox(height: 10),
Text('break your big goal into smaller achievable and measurable goals that you can achieve in short periods',textAlign: TextAlign.right, style: TextStyle(color: Colors.pink[500], fontSize: 20),)
],
),

),
),
TimelineDivider(
thickness: 4,
color: Colors.pink,
begin: 0.055,
end: 0.945,
axis: TimelineAxis.horizontal,
),

//4
TimelineTile(
axis: TimelineAxis.vertical,
alignment: TimelineAlign.manual,
lineXY: 0.99,
indicatorStyle: IndicatorStyle(
width: 40,
height:40,
indicator: Container(
width: 50,
height: 50,
child: Center(child: Text('4', style: TextStyle(fontSize: 26, color: Colors.white, fontFamily: 'Dancing Script'),)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.pink
),
)
),
beforeLineStyle: LineStyle(color: Colors.pink),
afterLineStyle: LineStyle(color:Colors.pink),
startChild: Container(
width: 50,
height: 140,
margin: EdgeInsets.only(top: 20, bottom: 10, left: 50, right: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Discipline!', textAlign: TextAlign.left, style: TextStyle(color: Colors.pink, fontWeight: FontWeight.bold, fontSize: 24),),
SizedBox(height: 10),
Text('be consistent and finish your daily tasks. Don\'t procrastinate and fight every excuse you make',textAlign: TextAlign.left, style: TextStyle(color: Colors.pink[500], fontSize: 20),)
],
),
),
),
TimelineDivider(
axis: TimelineAxis.horizontal,
begin: 0.055,
end: 0.945,
thickness: 4,
color: Colors.pink,
),
//5
TimelineTile(
axis: TimelineAxis.vertical,
alignment: TimelineAlign.manual,
lineXY: 0.01,
beforeLineStyle: LineStyle(color: Colors.pink),
indicatorStyle: IndicatorStyle(
width: 40,
height:40,
indicator: Container(
width: 50,
height: 50,
child: Center(child: Text('5', style: TextStyle(fontSize: 26, color: Colors.white, fontFamily: 'Dancing Script'),)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.pink
),

)
),
isLast: true,
endChild: Container(
margin: EdgeInsets.only(top: 20, left: 40, right: 10, bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text('Time Management!', textAlign: TextAlign.right, style: TextStyle(color: Colors.pink, fontWeight: FontWeight.bold, fontSize: 24),),
SizedBox(height: 10),
Text('Make sure to manage your time by doing tasks with higher priority first and allocate enough time to each task',textAlign: TextAlign.right, style: TextStyle(color: Colors.pink[500], fontSize: 20),)
],
),
),
),

],
),
),
),
)
flutter timeline tile example

Conclusion

Wooo, you’ve just finished Flutter timeline tile example! Congrats!

It’s very practical to learn how to implement timelines in your apps as they’ve become very popular. We learnt how to create timeline tile in both vertical and manual alignment. In addition, we learnt how to use Timeline divider to create beautiful timeline UI.

If you wish to learn more about Flutter, I have a whole category called Flutter that’s ripe for you to explore. You can learn about Flutter widgets, layouts, onboarding screen, tabbar, inkwell and gesture detector, stepper, listviews, gridviews, In-app messages, and practice with a bunch of real examples and many more!

Also, don’t forget to like and share my Facebook page, share the post with those who care to learn, and subscribe to my blog to be one of the firsts to know about my newest posts!

Thank you!

Oh hi there!
It’s nice to meet you.

Sign up to receive awesome content in your inbox, every month.

Let's Do This!

Leave a Reply

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

Scroll to top