├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Timeline.png
├── example
└── example.dart
├── lib
├── model
│ └── timeline_model.dart
├── timeline.dart
├── timeline_element.dart
└── timeline_painter.dart
├── pubspec.yaml
└── timeline.iml
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | build/
8 | ios/.generated/
9 | ios/Flutter/Generated.xcconfig
10 | ios/Runner/GeneratedPluginRegistrant.*
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [0.0.1] - Release
2 |
3 | * A very basic timeline to display a series of events in the provided order.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2018 Rejish Radhakrishnan
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Timeline
2 |
3 | A flutter package that allows you to create basic timelines on your flutter application. This is customizable and easy to plugin to your application. You will find the following features:
4 |
5 | * A simple timeline with a title and a description
6 | * Customizable color options for - Line, Title, Description and Background
7 | * Tween animation on the line
8 | * Title will be truncated at 47 characters to prevent overflowing
9 | * Description will be truncated at 75 character to prevent overflowing
10 |
11 |
12 |
13 | ## Getting Started
14 |
15 | You will need to add the following dependency in your `pubspec.yaml` file to download the depedency.
16 |
17 | ```dart
18 | dependencies:
19 | flutter:
20 | sdk: flutter
21 | timeline: 0.0.1
22 | ```
23 | Note: This was built on the following tools.
24 |
25 | * Flutter - v0.4.4
26 | * Dart - v2.0.0-dev.54.0
27 |
28 | ### Usage
29 |
30 | You will need to create a list of `TimelineModel` first. This creates an instance with an `id` which is a String at the moment, along with `title` and `description`
31 |
32 | [Example](https://github.com/rejish4gt/flutter-timeline/blob/master/example/example.dart)
33 |
34 | ## Contributing
35 |
36 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
37 |
38 | ## Authors
39 |
40 | * **Rejish Radhakrishnan**
41 |
42 | ## License
43 |
44 | Copyright 2018 Rejish Radhakrishnan
45 |
46 | Licensed under the Apache License, Version 2.0 (the "License");
47 | you may not use this file except in compliance with the License.
48 | You may obtain a copy of the License at
49 |
50 | http://www.apache.org/licenses/LICENSE-2.0
51 |
52 | Unless required by applicable law or agreed to in writing, software
53 | distributed under the License is distributed on an "AS IS" BASIS,
54 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
55 | See the License for the specific language governing permissions and
56 | limitations under the License.
57 |
--------------------------------------------------------------------------------
/Timeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rejish4gt/flutter-timeline/74a59586463827d10bfa39ad8cbba0ed2440404d/Timeline.png
--------------------------------------------------------------------------------
/example/example.dart:
--------------------------------------------------------------------------------
1 | import "package:flutter/material.dart";
2 | import 'package:timeline/model/timeline_model.dart';
3 | import 'package:timeline/timeline.dart';
4 |
5 | class TimelineExample extends StatelessWidget {
6 |
7 | final List list = [
8 | TimelineModel(
9 | id: "1",
10 | description: "Test 1",
11 | title: "Test 1"),
12 | TimelineModel(
13 | id: "2",
14 | description: "Test 2",
15 | title: "Test 2")
16 | ];
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return new TimelineComponent(
21 | timelineList: list,
22 | // lineColor: Colors.red[200], // Defaults to accent color if not provided
23 | // backgroundColor: Colors.black87, // Defaults to white if not provided
24 | // headingColor: Colors.black, // Defaults to black if not provided
25 | // descriptionColor: Colors.grey, // Defaults to grey if not provided
26 | );
27 | }
28 |
29 |
30 | }
--------------------------------------------------------------------------------
/lib/model/timeline_model.dart:
--------------------------------------------------------------------------------
1 | /* Copyright 2018 Rejish Radhakrishnan
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | class TimelineModel {
16 | final String id;
17 | final String title;
18 | final String description;
19 |
20 | const TimelineModel({this.id, this.title, this.description});
21 | }
--------------------------------------------------------------------------------
/lib/timeline.dart:
--------------------------------------------------------------------------------
1 | /* Copyright 2018 Rejish Radhakrishnan
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | library timeline;
16 |
17 | import 'package:flutter/material.dart';
18 | import 'package:timeline/model/timeline_model.dart';
19 | import 'package:timeline/timeline_element.dart';
20 |
21 | class TimelineComponent extends StatefulWidget {
22 |
23 | final List timelineList;
24 |
25 | final Color lineColor;
26 |
27 | final Color backgroundColor;
28 |
29 | final Color headingColor;
30 |
31 | final Color descriptionColor;
32 |
33 | const TimelineComponent({Key key, this.timelineList, this.lineColor, this.backgroundColor, this.headingColor, this.descriptionColor}) : super(key: key);
34 |
35 | @override
36 | TimelineComponentState createState() {
37 | return new TimelineComponentState();
38 | }
39 |
40 | }
41 |
42 | class TimelineComponentState extends State with SingleTickerProviderStateMixin{
43 |
44 | Animation animation;
45 | AnimationController controller;
46 | double fraction = 0.0;
47 |
48 | @override
49 | void initState() {
50 | super.initState();
51 | controller = AnimationController(
52 | duration: const Duration(milliseconds: 1000),
53 | vsync: this);
54 | controller.forward();
55 | }
56 |
57 | @override
58 | Widget build(BuildContext context) {
59 | return new Container(
60 | child: new ListView.builder(
61 | itemCount: widget.timelineList.length,
62 | itemBuilder: (_, index) {
63 | return new TimelineElement(
64 | lineColor: widget.lineColor==null?Theme.of(context).accentColor:widget.lineColor,
65 | backgroundColor: widget.backgroundColor==null?Colors.white:widget.backgroundColor,
66 | model: widget.timelineList[index],
67 | firstElement: index==0,
68 | lastElement: widget.timelineList.length==index+1,
69 | controller: controller,
70 | headingColor: widget.headingColor,
71 | descriptionColor: widget.descriptionColor,
72 | );
73 | },
74 | ),
75 | );
76 | }
77 |
78 | @override
79 | void dispose() {
80 | controller.dispose();
81 | super.dispose();
82 | }
83 |
84 | }
--------------------------------------------------------------------------------
/lib/timeline_element.dart:
--------------------------------------------------------------------------------
1 | /* Copyright 2018 Rejish Radhakrishnan
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | import 'package:flutter/material.dart';
16 | import 'package:timeline/model/timeline_model.dart';
17 | import 'timeline_painter.dart';
18 |
19 | class TimelineElement extends StatelessWidget {
20 |
21 | final Color lineColor;
22 | final Color backgroundColor;
23 | final TimelineModel model;
24 | final bool firstElement;
25 | final bool lastElement;
26 | final Animation controller;
27 | final Color headingColor;
28 | final Color descriptionColor;
29 |
30 | TimelineElement({
31 | @required this.lineColor,
32 | @required this.backgroundColor,
33 | @required this.model,
34 | this.firstElement = false,
35 | this.lastElement = false,
36 | this.controller,
37 | this.headingColor,
38 | this.descriptionColor
39 | });
40 |
41 | Widget _buildLine(BuildContext context, Widget child) {
42 | return new Container(
43 | width: 40.0,
44 | child: new CustomPaint(
45 | painter: new TimelinePainter(
46 | lineColor: lineColor,
47 | backgroundColor: backgroundColor,
48 | firstElement: firstElement,
49 | lastElement: lastElement,
50 | controller: controller
51 | ),
52 | ),
53 | );
54 | }
55 |
56 | Widget _buildContentColumn(BuildContext context) {
57 | return new Column(
58 | mainAxisSize: MainAxisSize.max,
59 | crossAxisAlignment: CrossAxisAlignment.start,
60 | children: [
61 | new Container(
62 | padding: const EdgeInsets.only(bottom: 8.0, top: 8.0),
63 | child: new Text(
64 | model.title.length>47?model.title.substring(0,47)+"...":model.title,
65 | style: new TextStyle(
66 | fontWeight: FontWeight.bold,
67 | color: headingColor!=null?headingColor:Colors.black,
68 | ),
69 | ),
70 | ),
71 | new Expanded(
72 | child: new Text(
73 | model.description!=null?(model.description.length>50?model.description.substring(0,50)+"...":model.description):"", // To prevent overflowing of text to the next element, the text is truncated if greater than 75 characters
74 | style: new TextStyle(
75 | color: descriptionColor!=null?descriptionColor:Colors.grey,
76 | ),
77 | ),
78 | )
79 | ],
80 | );
81 | }
82 |
83 | Widget _buildRow(BuildContext context)
84 | {
85 | return new Container(
86 | height: 80.0,
87 | color: backgroundColor,
88 | padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 0.0),
89 | child: new Row(
90 | crossAxisAlignment: CrossAxisAlignment.stretch,
91 | children: [
92 | new AnimatedBuilder(
93 | builder: _buildLine,
94 | animation: controller,
95 | ),
96 | new Expanded(
97 | child: _buildContentColumn(context),
98 | ),
99 | ],
100 | ),
101 | );
102 | }
103 |
104 | @override
105 | Widget build(BuildContext context) {
106 | return _buildRow(context);
107 | }
108 |
109 | }
--------------------------------------------------------------------------------
/lib/timeline_painter.dart:
--------------------------------------------------------------------------------
1 | /* Copyright 2018 Rejish Radhakrishnan
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License. */
14 |
15 | import 'dart:ui';
16 | import 'package:flutter/material.dart';
17 |
18 | class TimelinePainter extends CustomPainter {
19 |
20 | final Color lineColor;
21 | final Color backgroundColor;
22 | final bool firstElement;
23 | final bool lastElement;
24 | final Animation controller;
25 | final Animation height;
26 |
27 | TimelinePainter({
28 | @required this.lineColor,
29 | @required this.backgroundColor,
30 | this.firstElement = false,
31 | this.lastElement = false,
32 | this.controller
33 | }) :height = new Tween(begin: 0.0, end: 1.0).animate(new CurvedAnimation(
34 | parent: controller,
35 | curve: new Interval(
36 | 0.45, 1.0,
37 | curve: Curves.ease),
38 | ),
39 | ),
40 | super(repaint: controller);
41 |
42 | @override
43 | void paint(Canvas canvas, Size size) {
44 | _centerElementPaint(canvas, size);
45 | }
46 |
47 | void _centerElementPaint(Canvas canvas, Size size)
48 | {
49 | Paint lineStroke = new Paint()
50 | ..color = lineColor
51 | ..strokeCap = StrokeCap.round
52 | ..strokeWidth = 2.0
53 | ..style = PaintingStyle.stroke;
54 | if(firstElement && lastElement)
55 | {
56 | // Do nothing
57 | }
58 | else if(firstElement)
59 | {
60 | Offset offsetCenter = size.center(new Offset(0.0, -4.0));
61 | Offset offsetBottom = size.bottomCenter(new Offset(0.0, 0.0));
62 | Offset renderOffset = new Offset(offsetBottom.dx, offsetBottom.dy*(0.5+(controller.value/2)));
63 | canvas.drawLine(
64 | offsetCenter,
65 | renderOffset,
66 | lineStroke);
67 | }
68 | else if(lastElement)
69 | {
70 | Offset offsetTopCenter = size.topCenter(new Offset(0.0, 0.0));
71 | Offset offsetCenter = size.center(new Offset(0.0, -4.0));
72 | Offset renderOffset = new Offset(offsetCenter.dx, offsetCenter.dy*controller.value);
73 | canvas.drawLine(
74 | offsetTopCenter,
75 | renderOffset,
76 | lineStroke);
77 | }
78 | else {
79 | Offset offsetTopCenter = size.topCenter(new Offset(0.0, 0.0));
80 | Offset offsetBottom = size.bottomCenter(new Offset(0.0, 0.0));
81 | Offset renderOffset = new Offset(offsetBottom.dx, offsetBottom.dy*controller.value);
82 | canvas.drawLine(
83 | offsetTopCenter,
84 | renderOffset,
85 | lineStroke);
86 | }
87 |
88 |
89 | Paint circleFill = new Paint()
90 | ..color = lineColor
91 | ..style = PaintingStyle.fill;
92 |
93 | canvas.drawCircle(size.center(new Offset(0.0, -8.0)), 6.0, circleFill);
94 |
95 | }
96 |
97 | @override
98 | bool shouldRepaint(TimelinePainter oldDelegate) {
99 | return oldDelegate.lineColor!=lineColor || oldDelegate.backgroundColor!=backgroundColor;
100 | }
101 |
102 | }
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: timeline
2 | description: A new flutter package project.
3 | version: 0.0.1
4 | author: Rejish Radhakrishnan
5 | homepage: https://github.com/rejish4gt/flutter-timeline
6 |
7 | dependencies:
8 | flutter:
9 | sdk: flutter
10 |
11 | dev_dependencies:
12 | flutter_test:
13 | sdk: flutter
14 |
15 | # For information on the generic Dart part of this file, see the
16 | # following page: https://www.dartlang.org/tools/pub/pubspec
17 |
18 | # The following section is specific to Flutter.
19 | flutter:
20 |
21 | environment:
22 | sdk: ">=2.0.0-dev.54.0 <3.0.0"
23 | # To add assets to your package, add an assets section, like this:
24 | # assets:
25 | # - images/a_dot_burr.jpeg
26 | # - images/a_dot_ham.jpeg
27 | #
28 | # For details regarding assets in packages, see
29 | # https://flutter.io/assets-and-images/#from-packages
30 | #
31 | # An image asset can refer to one or more resolution-specific "variants", see
32 | # https://flutter.io/assets-and-images/#resolution-aware.
33 |
34 | # To add custom fonts to your package, add a fonts section here,
35 | # in this "flutter" section. Each entry in this list should have a
36 | # "family" key with the font family name, and a "fonts" key with a
37 | # list giving the asset and other descriptors for the font. For
38 | # example:
39 | # fonts:
40 | # - family: Schyler
41 | # fonts:
42 | # - asset: fonts/Schyler-Regular.ttf
43 | # - asset: fonts/Schyler-Italic.ttf
44 | # style: italic
45 | # - family: Trajan Pro
46 | # fonts:
47 | # - asset: fonts/TrajanPro.ttf
48 | # - asset: fonts/TrajanPro_Bold.ttf
49 | # weight: 700
50 | #
51 | # For details regarding fonts in packages, see
52 | # https://flutter.io/custom-fonts/#from-packages
53 |
--------------------------------------------------------------------------------
/timeline.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------