├── .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 | --------------------------------------------------------------------------------