A powerful & easy to use timeline package for Flutter! 🚀

Overview

banner

Pub Awesome Flutter License: MIT

A powerful & easy to use timeline package for Flutter! 🚀

Caveat: This package is an early stage. Not enough testing has been done to guarantee stability. Some APIs may change.

Examples

Check it out on the web or look at the source code.

Timeline status Package delivery tracking Process timeline
timeline_status package_delivery_tracking.gif process_timeline.gif

More examples
🚧 WIP 🚧

Features

The timeline and each components are all WIDGET.

  • Common styles can be easily implemented with predefined components.
  • Vertical, horizontal direction.
  • Alternating contents.
  • Combination with Flutter widgets(Row, Column, CustomScrollView, etc).
  • Customize each range with themes.

Getting started

Installation

1. Depend on it

Add this to your package's pubspec.yaml file:

dependencies:
  timelines: ^[latest_version]

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:timelines/timelines.dart';

Basic Usage

@override
Widget build(BuildContext context) {
  return Timeline.tileBuilder(
    builder: TimelineTileBuilder.fromStyle(
      contentsAlign: ContentsAlign.alternating,
      contentsBuilder: (context, index) => Padding(
        padding: const EdgeInsets.all(24.0),
        child: Text('Timeline Event $index'),
      ),
      itemCount: 10,
    ),
  );
}

Check the Example or the API reference for more details.

Components

Theme

Check out Theme Demo to see how the values inside TimelineTile work with the theme.

To customize the timeline component with a theme, do the following:

TimelineTheme(
  data: TimelineThemeData(...),
  child: DotIndicator(...),
);

If you only want to change part of the parent theme, use TimelineTheme.of(context):

TimelineTheme(
  data: TimelineThemeData.of(context).copyWith(...),
  child: DotIndicator(...),
);

If the component you want to customize is Timeline or FixedTimeline, this is also possible:

FixedTimeline(
  theme: TimelineThemeData(...),
  children: [...],
);

Indicator

ContainerIndicator
ContainerIndicator
ContainerIndicator(
  child: Container(
    width: 15.0,
    height: 15.0,
    color: Colors.blue,
  ),
)
DotIndicator
DotIndicator
DotIndicator()
OutlinedDotIndicator
OutlinedDotIndicator
OutlinedDotIndicator()

Connector

SolidLineConnector
SolidLineConnector
SizedBox(
  height: 20.0,
  child: SolidLineConnector(),
)
DashedLineConnector
DashedLineConnector
SizedBox(
  height: 20.0,
  child: DashedLineConnector(),
)
DecoratedLineConnector
DecoratedLineConnector
SizedBox(
  height: 20.0,
  child: DecoratedLineConnector(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [Colors.blue, Colors.lightBlueAccent[100]],
      ),
    ),
  ),
)

TimelineNode

Pure timeline UI component with no content.

The TimelineNode contains an indicator and two connectors on both sides of the indicator:

Simple TimelineNode
Simple TimelineNode
SizedBox(
  height: 50.0,
  child: TimelineNode.simple(),
)
Complex TimelineNode
Complex TimelineNode
SizedBox(
  height: 80.0,
  child: TimelineNode(
    indicator: Card(
      margin: EdgeInsets.zero,
      child: Padding(
        padding: EdgeInsets.all(8.0),
        child: Text('Complex'),
      ),
    ),
    startConnector: DashedLineConnector(),
    endConnector: SolidLineConnector(),
  ),
)

TimelineTile

Displays content on both sides of the node:

TimelineTile
TimelineTile
TimelineTile(
  oppositeContents: Padding(
    padding: const EdgeInsets.all(8.0),
    child: Text('opposite\ncontents'),
  ),
  contents: Card(
    child: Container(
      padding: EdgeInsets.all(8.0),
      child: Text('contents'),
    ),
  ),
  node: TimelineNode(
    indicator: DotIndicator(),
    startConnector: SolidLineConnector(),
    endConnector: SolidLineConnector(),
  ),
)

TimelineTileBuilder

TimelineTileBuilder provides powerful build features.

Connection

Each tile draws only half of the line connecting the neighboring tiles. Using the connected constructor, lines connecting adjacent tiles can build as one index.

ConnectionDirection.before
Connection direction before
FixedTimeline.tileBuilder(
  builder: TimelineTileBuilder.connectedFromStyle(
    connectionDirection: ConnectionDirection.before,
    connectorStyleBuilder: (context, index) {
      return (index == 1) ? ConnectorStyle.dashedLine : ConnectorStyle.solidLine;
    },
    indicatorStyleBuilder: (context, index) => IndicatorStyle.dot,
    itemExtent: 40.0,
    itemCount: 3,
  ),
)
ConnectionDirection.after
Connection direction after
FixedTimeline.tileBuilder(
  builder: TimelineTileBuilder.connectedFromStyle(
    connectionDirection: ConnectionDirection.after,
    connectorStyleBuilder: (context, index) {
      return (index == 1) ? ConnectorStyle.dashedLine : ConnectorStyle.solidLine;
    },
    indicatorStyleBuilder: (context, index) => IndicatorStyle.dot,
    itemExtent: 40.0,
    itemCount: 3,
  ),
)

ContentsAlign

This value determines how the contents of the timeline will be built:

ContentsAlign.basic
Basic contents align
FixedTimeline.tileBuilder(
  builder: TimelineTileBuilder.connectedFromStyle(
    contentsAlign: ContentsAlign.basic,
    oppositeContentsBuilder: (context, index) => Padding(
      padding: const EdgeInsets.all(8.0),
      child: Text('opposite\ncontents'),
    ),
    contentsBuilder: (context, index) => Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text('Contents'),
      ),
    ),
    connectorStyleBuilder: (context, index) => ConnectorStyle.solidLine,
    indicatorStyleBuilder: (context, index) => IndicatorStyle.dot,
    itemCount: 3,
  ),
)
ContentsAlign.reverse
Reverse contents align
FixedTimeline.tileBuilder(
  builder: TimelineTileBuilder.connectedFromStyle(
    contentsAlign: ContentsAlign.reverse,
    oppositeContentsBuilder: (context, index) => Padding(
      padding: const EdgeInsets.all(8.0),
      child: Text('opposite\ncontents'),
    ),
    contentsBuilder: (context, index) => Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text('Contents'),
      ),
    ),
    connectorStyleBuilder: (context, index) => ConnectorStyle.solidLine,
    indicatorStyleBuilder: (context, index) => IndicatorStyle.dot,
    itemCount: 3,
  ),
)
ContentsAlign.alternating
Alternating contents align
FixedTimeline.tileBuilder(
  builder: TimelineTileBuilder.connectedFromStyle(
    contentsAlign: ContentsAlign.alternating,
    oppositeContentsBuilder: (context, index) => Padding(
      padding: const EdgeInsets.all(8.0),
      child: Text('opposite\ncontents'),
    ),
    contentsBuilder: (context, index) => Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text('Contents'),
      ),
    ),
    connectorStyleBuilder: (context, index) => ConnectorStyle.solidLine,
    indicatorStyleBuilder: (context, index) => IndicatorStyle.dot,
    itemCount: 3,
  ),
)

Timeline

The timeline component has two widgets, Timeline similar to ScrollView and FixedTimeline similar to Flex.

Also their constructors are similar to ScrollView and Flex.

The main difference is that they has TimelineTheme as an ancestor.

The tileBuilder constructor provides more powerful features using TimelineTileBuilder.

If you don't need TimelineTileBuilder, you can use other flutter widgets like ListView, Column, Row, etc.

Even if you use the flutter widget, you can use TimelineTheme.

Documentation

See full documentation

Changelog

See CHANGELOG.md.

Code of conduct

See CODE_OF_CONDUCT.md.

License

MIT

Comments
  • Add null safety support

    Add null safety support

    This PR closes #31 .

    I followed the steps mentioned on this page.

    Some points to mention :

    • Widget-returning functions which returned null now return const SizedBox(), which is an empty Widget
    • as tere is not many tests for this plugin, we could use some more manual testing
    opened by areille 6
  • Question : How to align the nodes to the left ?

    Question : How to align the nodes to the left ?

    Hi,

    I would like to align the nodes to the left in order to have a fixed size for the content and the remaining space for the opposite content. There is a property nodeAlign in TimelineTile that used to compute the effective node position :

      double _getEffectiveNodePosition(BuildContext context) {
        if (nodeAlign == TimelineNodeAlign.start) return 0.0;
        if (nodeAlign == TimelineNodeAlign.end) return 1.0;
        var nodePosition = this.nodePosition;
        nodePosition ??= (node is TimelineTileNode)
            ? (node as TimelineTileNode).getEffectivePosition(context)
            : TimelineTheme.of(context).nodePosition;
        return nodePosition;
      }
    

    This property can't be used in TimelineTileBuilder so please what is the simplest way to define the nodeAlign ?

    opened by adbonnin 5
  • Vertical align indicators with item content

    Vertical align indicators with item content

    Thanks for the promising plugin. Is there any way to control vertical positioning of the indicators? For example, if I use larger titles, can I force the indicators down in order to line them up with the content titles better ? Here's the problem I'm facing:

    Screenshot_20201209-081739

    and my item builder:

                contentsBuilder: (context, index) => Padding(
                padding: const EdgeInsets.only(
                  left: 30,
                  bottom: 30,
                  right: 30,
                ),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Timeline Event $index',
                      textScaleFactor: 3,
                    ),
                    SizedBox(height: 10),
                    Text('Nam libero tempore, cum soluta nobis...') // truncated for brevity here
                  ],
                ),
              ),
    

    But it's not clear to me how I can shift the indicators down, either all together, or individually, in order to line up with the titles better...? Thanks.

    opened by frmatthew 5
  • null-safety release is not available

    null-safety release is not available

    Hi, according to the changelog there should be a version available 0.1.0-null which includes null-safety changes, but when I try to set this version in my pubspec.yaml then I get an error that this version is not available

    pubspec.yaml:

    timelines: 0.1.0-null
    

    error:

    Because project depends on timelines 0.1.0-null which doesn't match any versions, version solving failed.
    

    version from pub.dev: image

    opened by jseminck 2
  • Documentation and examples are not clear

    Documentation and examples are not clear

    The Showcase screen in the code example only shows png files with the results, but how are they implemented?

    How can I control each connector and each Node? I want the connectors be in in different lengths and have different Icon on each Node.

    opened by ronytesler 2
  • SolidLineConnector and other connectors should have a child parameter.

    SolidLineConnector and other connectors should have a child parameter.

    I want to create a custom timeline. A TimelineTile that will show contents, with a node that has a custom indicator. The node has an endConnector parameter that I think the connector widget should have a child parameter in case you want to connect to another TimeLineTile.

               TimelineTile(
                 contents: const Padding(
                   padding: EdgeInsets.all(8.0),
                   child: Text(
                     "WORK EXPERIENCE",
                     style: TextStyle(
                         color: Colors.white, fontWeight: FontWeight.bold),
                   ),
                 ),
                 node: TimelineNode(
                   endConnector: const SolidLineConnector(
                     color: Colors.white,
                   ),
                   indicator: Container(
                     width: 50,
                     height: 50,
                     decoration: BoxDecoration(
                         borderRadius: BorderRadius.circular(25),
                         color: HexColor('#eab676')),
                     child: const Icon(
                       Icons.work,
                       color: Colors.white,
                     ),
                   ),
                 ),
               ),
             )),
    
    opened by AlexMainaMunyua 1
  • Alignment issues when indicators are not all the same size.

    Alignment issues when indicators are not all the same size.

    I have a list of indicators, where all aren't exactly the same size. There appears to be some distortion in the line connector as shown below:

    Any ideas how to resolve?

    opened by Mastersam07 1
  • How to change contentsAlign for individual items.

    How to change contentsAlign for individual items.

    Was unable to find any clue in the documentation on how to use different contentsAlign for different items.

    Im trying to use reverse align for some items in the timeline.

    Example: For a timeline of football/soccer match, events come from both teams. Is it possible to use 'reverse' for the "away" team events only?

    Please let me know if it is possible. Thank you

    opened by ashamnx 1
  • Stacked InnerTimeline

    Stacked InnerTimeline

    Thanks for contribute this plugin.

    i faced Stacked InnerTimeline issue.

    i want to display 3 line in InnerTimeline (inside contentsBuilder) so it only work 2 line.

    here is my code:

    contentsBuilder: (_, index) {
                if (isEdgeIndex(index)) {
                  return null;
                }
                return Container(
                  padding: EdgeInsets.only(left: 8.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Flexible(
                        child: Text(
                          childs[index -1].note ?? "",
                          style: TextStyle(
                            color: Color(0xFF4964D8),
                            fontSize: 16.0,
                            fontWeight: FontWeight.w500,
                            fontFamily: 'AvenirRoman',
                          ),
                        )
                      ),
                      // Flexible(child: _buildTags(childs[index - 1].tags)),
                      Flexible(
                        child: Text(
                          myParseDatetime1(childs[index - 1].createdAt),
                          style: TextStyle(
                            color: Color(0xFFA8A8A8),
                            fontSize: 14.0,
                            fontWeight: FontWeight.w500,
                            fontFamily: 'AvenirRoman',
                          ),
                        )
                      ),
                      Text('123')
                    ],
                  ),
                );
    
              },
    
    Screen Shot 2021-01-06 at 16 52 53

    here is 2 line. it's work

    Screen Shot 2021-01-06 at 17 00 31 question 
    opened by ngockhanhbl 1
  • Update internal links in Readme

    Update internal links in Readme

    This PR replaces the full Github URLs used for accessing different sections in the Readme with anchor links. It avoids reloading the page and thus makes it easier and faster to navigate.

    For instance, [Installation](https://github.com/chulwoo-park/timelines/tree/main#installation) is replaced with [Installation(#installation).

    opened by Akora-IngDKB 0
  • Pagination with timeline

    Pagination with timeline

    Hey, I'm trying to implement pagination with timelines. Currently, I'm wrapping timelines in a listview. But that leads to the complete timeline being rebuilt on each change. Is there any way to use a ListView.builder() like extending of the timeline?

    The best solution would be to only draw the items currently visible on the screen and extend the timeline on the fly.

    opened by hey-nicolasklein 0
  • Question: timeline branching?

    Question: timeline branching?

    Hello and thanks for making this package. I am wondering if you have any plans of implementing the ability to have parallel timelines similar to what you might see in a git history graph;

    image

    This may be a feature I would want for a personal project of mine and if I do end up needing it, I would be more than happy to contribute the code to this awesome package!

    opened by logiczsniper 0
  • Possible integration with video_player

    Possible integration with video_player

    Hi :) First of all, thanks you for such great package. After all these days of seraching, it seems to me I found the right place to ask.

    So I would like to create the timeline (or something like archive) for my videostream. The issue is quite non-trivial and hard, because videostream dosen't have the end. I could say, it is infinite videostream if we would scroll it back. Also the timeline should be under the videostream and I would like to have acess to it by double tap. So my question is could I customize it like I described above? And could I make the post-request to put two timestapms? Can these package work with API-request?

    opened by ingvilow 0
  • Question: Top alignment between content and indicator

    Question: Top alignment between content and indicator

    How can I align the top of the indicator with the top of the content, when the content is longer than a single line?

    Basically making sure the two red lines are aligned in the following example:

    Screenshot 2022-01-10 at 11 15 04

    Is there any option to accomplish this already?

    Thanks

    opened by robertoestivill 4
Releases(0.1.0)
  • 0.1.0(Mar 27, 2021)

  • 0.0.2+1(Nov 23, 2020)

  • 0.0.2(Nov 23, 2020)

    Add basic components

    Timeline

    • TimelineTheme
    • Timeline
    • FixedTimeline

    TimelineTile

    • TimelineTile
    • TimelineTileBuilder

    TimelineNode

    • TimelineNode

    Connector

    • ConnectorTheme
    • Connector
    • SolidLineConnector
    • DecoratedLineConnector
    • DashedLineConnector
    • TransparentConnector

    Indicator

    • IndicatorTheme
    • ContainerIndicator
    • DotIndicator
    • OutlinedDotIndicator

    Add demo web

    Source code(tar.gz)
    Source code(zip)
Owner
Chulwoo Park
Android, Flutter
Chulwoo Park
This package provides some widgets you can use to create a smooshy UI.

Dough Library Squishy widgets for Flutter. Quick Links Dough Demos Here are a few samples of the different widgets provided by this repo. You can find

Josiah Saunders 530 Dec 23, 2022
A highly customisable Flutter widget for entering pin code. Suitable for use cases such as login and OTP.

pin_code_text_field It's a beautiful and highly customizable Flutter widget for entering pin code. Suitable for use cases such as login and OTP. Usage

Liew Jun Tung 309 Dec 28, 2022
A complete, ready to use, Neumorphic ui kit for Flutter, 🕶️ dark mode compatible

flutter_neumorphic A complete, ready to use, Neumorphic ui kit for Flutter Try Flutter-Neumorphic on your browser : ?? https://flutter-neumorphic.fire

Idean 1.6k Jan 1, 2023
WooCommerce API - E-commerce Flutter v2.0 / USE block and architecture

Sonoff sonoffkz App - Woocommerce API Description Моя вторая версия магазина в открытом репозитории: при использовании стейт менеджемента BLoC и удобн

Maximus Edward An 1 May 10, 2022
A plugin for `flutter_map` that enables the use of vector tiles.

vector_map_tiles A plugin for flutter_map that enables the use of vector tiles. Usage class _MyHomePageState extends State<MyHomePage> { // provide

David Green 78 Jan 7, 2023
A flutter package which makes it easier to display the difference between two images.

?? Before After A flutter package which makes it easier to display the differences between two images.. The source code is 100% Dart, and everything r

Sahil Kumar 741 Dec 30, 2022
A flutter package to help you beautify your app popups.

flutter_beautiful_popup 中文 A flutter package to help you beautify your app popup, can be used in all platform.Live Demo. Preview: Getting Started Add

朱嘉伟 568 Dec 30, 2022
A flutter package for building card based forms.

Card Settings NOTE: THIS IS EFFECTIVELY NULLSAFE BUT CANNOT REFLECT THIS UNTIL cupertino_settings IS UPGRADED. A flutter package for building settings

CodeGrue 445 Dec 26, 2022
A package to help build customisable timelines in Flutter.

TimelineTile A package to help build customisable timelines in Flutter. Example You can access the example project for a Timeline Showcase. The Beauti

null 549 Jan 6, 2023
This Dart package offers developers a streamlined library of Flutter widgets, useful for expanding widgets and text views, when users interact with them.

This Dart package offers developers a streamlined library of Flutter widgets, useful for expanding widgets and text views, when users interact with them.

Jesús Rodríguez 44 Dec 6, 2022
A Flutter package that provides an Emoji picker widget with 1500+ emojis in 8 categories.

emoji_picker_flutter Yet another Emoji Picker for Flutter ?? Note: This package is based on emoji_picker which has been deprecated and not maintained

Stefan Humm 99 Dec 24, 2022
A Flutter package that enables users to resize the internal widgets by dragging.

resizable_widget ResizableWidget enables users to resize the internal widgets by dragging. This package contains simple APIs, but if needed, you can c

null 35 Dec 2, 2022
A flutter package to display a country, states, and cities. In addition it gives the possibility to select a list of countries, States and Cities depends on Selected, also you can search country, state, and city all around the world.

A flutter package to display a country, states, and cities. In addition it gives the possibility to select a list of countries, States and Cities depends on Selected, also you can search country, state, and city all around the world.

Altaf Razzaque 25 Dec 20, 2022
A flutter package that contains a collection of icon decoration tools (i.e. gradient, opacity) and icon transition features with cool animation effects.

Advanced Icon A flutter package that contains a collection of icon decoration tools (i.e. gradient, opacity) and icon transition features with cool an

Ankit Mishra 8 Dec 24, 2021
A new Flutter package support scroll to index for Listview, Gridview and NestedScrollView

easy_scroll_to_index A new Flutter package support scroll to index for Listview, Gridview and NestedScrollView Author: DinhVanHung Demo Example: Displ

Dinh Hung 4 Nov 19, 2021
Flutter package - Animated Flip Card

Animated Flip Card Animated Flip Card package lets you add an animated flip card to your Flutter app that hide and show more informations. Features Th

Ulfhrafn 8 Dec 4, 2022
A flutter port of Cardidy, a package to validate or identify card numbers & cvv with ease.

Flutter Cardidy A plugin to validate or identify card numbers & cvv with ease. This flutter package will help you validate card numbers or CVVs and id

Heyramb Narayan Goyal 1 Nov 28, 2021
Flutter package designed to select an item from a list, with the option to filter and even search the items online.

select_dialog Package Package designed to select an item from a list, with the option to filter and even search the items online. Versions Non Null Sa

David Araujo 63 Dec 10, 2022
A Flutter package to easily create a Credit Card in your application.

Awesome Card A flutter package to create a Credit Card widget in your application. Stay tuned for the latest updates: ?? Screenshots ⚙️ Installation I

Vivek Kaushik 142 Dec 1, 2022