<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Flutter Charts - A Guide to Creating Custom Charts in Flutter | Infinum</title>
		<atom:link href="https://infinum.com/blog/charts-in-flutter/feed/" rel="self" type="application/rss+xml" />
		<link>https://infinum.com/blog/charts-in-flutter/</link>
		<description>Building digital products</description>
		<lastBuildDate>Thu, 16 Apr 2026 11:27:35 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>19093https://infinum.com/uploads/2022/01/charts-in-flutter-0.webp</url>
				</image>
				<title>How to Create Custom Flutter Charts</title>
				<link>https://infinum.com/blog/charts-in-flutter/</link>
				<pubDate>Fri, 17 Dec 2021 13:55:00 +0000</pubDate>
				<dc:creator>Luka Knezić</dc:creator>
				<guid isPermaLink="false">https://infinum.com/blog/charts-in-flutter/</guid>
				<description>
					<![CDATA[<p>Presenting information in graphs and charts can be tricky in Flutter due to poor template availability, but a possible solution is to create custom charts. </p>
<p>The post <a href="https://infinum.com/blog/charts-in-flutter/">How to Create Custom Flutter Charts</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-214"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	<strong>Flutter charts</strong> are a challenge to implement in mobile apps. Learn how to do it easier with this handy guide on creating charts that are ready for production. This article will help you navigate the abundance of <strong>charting libraries</strong>, showing you tricks for customization and smooth integration to bring your designer&#8217;s vision to life. Make your data pop in a fun and professional way for your <a href="https://infinum.com/mobile-web-apps/">mobile app</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	It’s not a secret that apps collect user data. Insight into some of that data is also available for app users. An efficient way to present the information is using visuals, specifically graphs and charts.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-100'
	>
	They are easy to implement when it comes to Android or iOS, but for designers and engineers working with <a href="https://infinum.com/mobile-web-apps/flutter/">Flutter</a>, it’s easier said than done due to a scarcity of chart templates at their disposal.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-103'
	>
	A possible solution is to create <strong>custom charts</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-105">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-106'
	>
	Creating custom Flutter charts</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-108">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-109'
	>
	Unlike chart templates, <strong>charting libraries</strong> available at our disposal are abundant. For example, I stumbled upon more than 128 packages for the keyword “charts” when writing. They aren’t perfect, though – most are lacking in customization or require adding some UI elements, making it almost impossible to replicate designers’ ideas.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	I’ve tested several available chart libraries, desperately trying to mold our data to fit in the chart and repeatedly failing because the developers had either missed or forgotten something. Don’t get me wrong, none of those libraries are bad per se, nor do developers like to reinvent charts that much.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-115'
	>
	Charts are challenging to make, especially when presenting an enormous amount of data in a neat visual that should be fully customizable and accurate. And that’s just half of what a chart is supposed to do. The next part would be displaying a legend for more straightforward data interpretation.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-117">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-118'
	>
	The grammar of graphics</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-122"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-120">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-121'
	>
	Leland Wilkinson has an excellent book about data representation called <strong>The Grammar of Graphics</strong>. It dissects in simple terms the repression of graphics and their rules into seven layers, from data to themes:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-125"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-123"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-124">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2022/01/charts-in-flutter-1-1400x751.webp				media='(max-width: 699px)'
				type=image/webp								height="751"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2022/01/charts-in-flutter-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="805"
															width="1500"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-128"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-126">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-127'
	>
	We can see that layers have their functions, namely they enable us to build new layers on top quickly. The book describes how to present any data in any way imaginable. Our library will be used mainly on mobile devices, so we will focus on drawing in rectangular coordinate space to save time.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-131"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-129">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-130'
	>
	We can also delegate some layers. For example, we have limited space on mobile where multiple charts in grid view might be overkill. That being said, we can delegate the facets layer to the developer. If necessary, it can be done using <code>GridView</code> and by adding multiple <code>Chart</code> widgets as children.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-134"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-132">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-133'
	>
	Working on a custom solution for Flutter charts</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-137"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-135">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-136'
	>
	We wanted a simple Flutter chart that allows for a lot more UI customization. Making a scatter diagram or pie chart is technically possible using this lib, but it would require a lot of work.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-140"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-138">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-139'
	>
	Back to <strong>The Grammar of Graphics</strong>, how could we use those layers, and what layers do we need to create simple charts? Following this will allow us to implement missing layers later if required.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-143"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-141"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-142">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2022/01/charts-in-flutter-2-1400x751.webp				media='(max-width: 699px)'
				type=image/webp								height="751"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2022/01/charts-in-flutter-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="805"
															width="1500"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-146"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-144">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-145'
	>
	Now that we know what layers we need to handle immediately, it no longer looks so intimidating. With just four layers, we will be able to see our data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-149"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-147">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-148'
	>
	Data</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-152"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-150">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-151'
	>
	Now that we know how to make our Flutter chart, we can start handling the data layer. <code>ChartData</code> will map data to chart items. There is also <code>ChartData.randomBarValues</code> that helps with testing when adding charts. Chart data is handling aesthetics as well for now – it will try to display all of the data in the list and scale the chart accordingly. You can change that with exact value by specifying the axisMin and axisMax, or you can change the valueAxisMaxOver. That will add ‘invisible’ data on the max value, acting as ‘padding’ on current data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-155"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-153">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-154'
	>
	Geometries</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-158"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-156">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-157'
	>
	Geometry is a layer that takes the item and decides how and where to draw it in the chart. By using <code>ItemPainter</code>, we can draw different items while passing the same data. We could also expand our <code>ChartItem&lt;T&gt;</code> to show additional or other data.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-161"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-159">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-160'
	>
	Having geometry separated is useful since that way we can show the data we want without reinventing the whole chart. For example, if you need to show a custom chart item with five values, it can be done by extending <code>ChartItem&lt;T&gt;</code> and <code>GeometryPainter&lt;T&gt;</code> to draw and show any item you want. You can even add your own item options by extending <code>ItemOptions</code>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-164"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-162">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-163'
	>
	Statistics</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-167"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-165">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-166'
	>
	<code>DataStrategy</code> is used to manipulate the data. Current strategies are <code>DefaultDataStrategy</code> and <code>StackDataStrategy</code>. For now, since we won’t be adding an <em>Aesthetics</em> layer at this time, <code>ChartData</code> will also handle the scale the data will use. Horizontal axis for the charts is by default linear.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-170"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-168">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-169'
	>
	Themes</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-173"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-171">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-172'
	>
	Themes are just things that decorate the<strong> Flutter chart</strong>. In our case, we added “2” layers of decoration, front-ground and back-ground decorations. That way, we can also control the decorations shown on the front and back of the items. The neat thing is that we can use the decoration we make in multiple different use cases while also allowing complete customizability by extending <code>DecorationPainter</code> new Decorations can easily be added.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-176"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-174">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-175'
	>
	Animating the Flutter charts </h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-179"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-177">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-178'
	>
	It’s not enough for charts to be customizable and flexible to satisfy the design and blend with the app. Usually, analytics screens will have filters or something similar that will change the chart. That chart should animate to a new state to keep the app looking fluid and smooth.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-182"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-180">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-181'
	>
	Making this was a bit of a challenge, but since we already had layers nicely set up, it was just a matter of getting layers to animate between states.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-185"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-183">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-184'
	>
	We added <code>lerp</code> functions to each layer. Making a new <code>ImplicitlyAnimatedWidget</code> would ensure users can add <code>AnimatedChart</code>, and it will automatically update when a change in chart state is detected.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-188"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-186">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-187'
	>
	Using Flutter charts in production</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-191"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-189">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-190'
	>
	We have significant experience <a href="https://infinum.com/work/?industries=healthcare">building healthcare apps</a>, and they always want to show data in some way. That gave us a chance to try our Flutter charts immediately in the app we were developing for the US market. It was a perfect test since the charts were complex, and each screen had a slightly different chart to show.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-194"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-192"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-193">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2022/01/charts-in-flutter-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="616"
															width="1369"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-197"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-195"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-196">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2022/01/charts-in-flutter-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="575"
															width="1369"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-200"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-198">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-199'
	>
	The library didn’t limit us in any way. We could easily create a custom extension and add it to the chart if something was missing. So, by using the library more and more, we added a variety of decorations that would later prove suitable for the charts we were yet to create.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-203"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-201">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-202'
	>
	Finally, to make sure we don’t break any of the existing decorations or item painters when adding new features, we added over 80 golden tests. Safety first!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-206"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-204">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-205'
	>
	Pixel perfect charts every time</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-209"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-207">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-208'
	>
	Using charts in production can be tricky, but <a href="https://github.com/infinum/flutter-charts">Flutter charts can help</a>. Try it out and help us make it better with feedback!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-212"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-210">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-211'
	>
	Infinum is proud to be enlisted in <a href="https://flutter.dev/consultants">Google’s Flutter Consultants Repository</a>. If you need a Flutter app that will elevate your business, <a href="https://infinum.com/contact/">get in touch</a> with us for top-notch development services.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/charts-in-flutter/">How to Create Custom Flutter Charts</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>