Drawing in Flutter. GradientColoredSlider - Part 1.
CustomPaint vs RenderObject.

We are going to create a slider widget with a thumb colored according to the selected value from a gradient color range:
As you can see this kind of widget requires a lot of custom drawing. To draw a widget like GradientColoredSlider we need an access to a canvas. We can do this via CustomPaint or RenderObject.

Package on
What's the difference between CustomPaint or RenderObject and which approach is right for us? First of all CustomPaint is a widget and can be used right away, but to deal with RenderObject we need a help of RenderObjectWidget which API allows to create it. RenderObject is used by the Flutter Framework to actually render widget's that are supposed to be layout and paint, because not each widget requires this, there are other types:

  • Composable containers, like StatefulWidget/StatelessWidget — to add our widget to the tree
  • 'Meta' widgets, like Theme, MediaQuery etc.
Those above types are not associated with RenderObject.

In Flutter Framework RenderObject is responsible for on-screen rendering of UI components: their sizing, layout, painting and compositioning.

Conceptually, Flutter's UI building blocks are Elements, all of your UI components is translated into Element Tree, and Widget's are used to pass specific properties to an Element, e.g. to set a background color (roughly, widgets may be compared with Builder pattern, where widget is use just to build an element), finally that configured piece of UI needs to be rendered — and that's the responsibility of RenderObjects.

To use RenderObject we need to extend RenderObjectWidget, which provides required API for this, check implementation of _GradientColoredSliderRenderObjectWidget.
Now, after we recollected the basics, let's decide what to stick with to draw our slider: CustomPaint or RenderObjectWidget.

On a system level, there is no difference - because CustomPaint itself is a RenderObjectWidget as it extends it:
The difference is that CustomPaint narrows RenderObject's Api just to canvas painting, while sizing, layout and gesture handling are supposed to be handled by dedicated Flutter widgets.

And CustomPaint is the right approach in most of the cases.

While going with RenderObject gives the following benefits to our GradientColoredSlider:

  1. usage of LeafRenderObject gives slight performance benefit.
  2. overriding isRepaintBoundary => true, prevents parents from redrawing. Otherwise, parent will redraw, even if setState() isn't used. In cases when widgets with expensive painting are used, that can give huge performance improvement. In the illustration below repaint of the upper slider happens in it's own layer, while bottom slider also causes a repaint of its parent.
Here is a great video on Flutter painting performance.

3. Flat structure. Sizing, layout, gesture handling, drawing are done in place, so less nested widgets — less elements — less RenderObjects. As a result less layout work for Flutter Engine, as no child-parent communication required, check the Flutter Layout Rule.

4. It is just more convenient. We found that going with CustomPaint would make GradientColoredSlider code too cumbersome, because of a need to pass between different element tree nodes dynamically obtained data related to each widget building aspect:
Code complexity = sizing * layout * gesture * drawing

  1. There is no significant performance advantage of a RenderObject over CustomPaint, as technically both approaches are similar. Repaint boundaries could be handled by the dedicated RepaintBoundary widget.
  2. Dealing with RenderObject is more complex and verbose compared to CustomPaint, where you deal just with a canvas.
  3. In most cases, it's better to use specially designed for drawing — CustomPaint.
  4. Use RenderObject directly when you need to draw depending on changing sizing, layout, and gesture handle simultaneously.
Source code on gitHub.

In Part 2 we'll cover:

  1. Sizing and Layout.
  2. Gesture handling.
  3. Drawing

Don't miss the latest news. Subscribe to our newsletter!
© 2021 All Right Reserved. KiRN Tech.
Quick and Smooth Mobile App Launch
For Your Startup.
Peremohy Ave. 26, Kyiv, Ukraine, 04116