How to bend / crook a Flutter widget? (non-affine widget render transform)

342

One approach: Use a CustomPaint to draw lines/areas/etc freely

You can use a CustomPaint to draw whatever curved lines, areas, etc freely. Therefore, you can definitely achieve your goal - since they are nothing but curved lines, areas with curved edges, rotated texts, etc. That will take a bit of work, but if you encapsulate it well enough, it is not that hard to implement. For example, draw a Path with filled red area, then draw a white arc, then draw several texts with calculated rotations, etc. Sounds like you can do that within maybe hundreds of lines. If you find difficulty implementing this please comment and I will explain.

Another approach: Hack Canvas such that the call to drawLine becomes indeed calls to drawPath, etc.

You may do the following to allow bend/crook for any widget (and their combination, of course), but this may need a bit of engineering. You can make your own Canvas, say, class BendCanvas implements Canvas {}. The BendCanvas.drawLine, for example, has an implementation of Canvas.drawPath with a curved path cooresponding to the input "line". Similar things hold for drawing rectangles, etc. Then you need to hack Flutter's painting logic, such that it takes in your own BendCanvas instead of the original canvas. This is a universal solution, and it is much more efficient (less code) if you plan to have a lot of bend UI; but if only on bend TabBar, maybe use the first approach.

As for the bend text

In the two approaches above, we have mainly described how you draw the bended rectangle (i.e. draw an arbitrary shaped widget). As for bending text, see: https://github.com/flutter/flutter/issues/16477 , which is still an open issue.

Remarks

It is not possible using transformations. As explained in the comments, you already see Transform does not work - it is affine or perspective, which, by definition, will not bend. Then what about other transforms? After some research there seems to be none. Then, what about looking under the scene. We know Flutter uses Skia under it to draw the UI with high performance, then let us search through Skia. However, it does not provide any transformations like bending. So there seems no use.

P.S. I am not that high reputation in Flutter tag, but I did answer >100 Flutter questions (including some dig-into-source-code style ones), and have developed >100k lines of Flutter code in the production app.

Share:
342
Rasto
Author by

Rasto

Entrepreneur, UX consultant, full-stack developer with strongest competency in Swift & iOS. Can get die-hard about top-notch UX and code quality. Diving deeper into React and getting excited about GraphQL. My pro history chapters are written in C#, Objective-C, Java, JS, TS, Flow, even Haskel, Prolog & Pascal. Sports and outdoor enthusiast. Love exploring cultures around the world. Found in mountains in the winter and at seaside during summer. Amater photographer. Always happy to learn and share what I learned e.g. externally giving lectures at my alma mater.

Updated on January 01, 2023

Comments

  • Rasto
    Rasto over 1 year

    Let's say you have some flutter widget, for example, a TabBar. It is rendered in a rectangular box. I need it to be rendered in an arc so that the text and the underline follow part of a circle (or better still, a bezier curve).

    How can that be achieved?

    This illustrates what I am trying to achieve - bent TabBar widget:

    enter image description here

    Please note that in this case, the TabBar bends following and an arc (edge of a circle). This is what I need immediately. However, in the future, I might need bending that follows the edge of an eclipse so a solution that allows it would be preferable.

    Also, a solution that works for different widgets is preferred.

    IMPORTANT: I do NOT want to clip a curved shape of the widget. The entire area of the widget should stay visible. Instead, I need to bend the content of the widget (=bend its render image).

    Apologies for the bold font but without it, people will keep posting answers about how to clip a widget which is trivial in comparison and useless for my problem.

    An answer "this is currently not supported by Flutter" from authority (e.g. high reputation in Flutter tag or Flutter a team member) will also be accepted.

  • Rasto
    Rasto over 2 years
    Finally some useful answer. Yes, unfortunately, I need the text to be bent as well. Any ideas there? Especially the with the third option, can it bend text? Also, I expect this to be one of my most popular questions in a few years. Therefore, as you answer might be the accepted one perhaps you want to shorten it a bit (remove description of the options that do not work) for it to be easier to read for future readers?
  • ch271828n
    ch271828n over 2 years
    @Rasto subsection title added to be clear to read; let me have a search at bend text.
  • ch271828n
    ch271828n over 2 years
    @Rasto a section of bending text is added. though that is still an open issue.
  • Phani Rithvij
    Phani Rithvij over 2 years
    @Rasto This developers.mews.com/flutter-how-to-draw-text-along-arc was mentioned in the linked skia issue for curved text support in one of the comments. This answer along with this tutorial could work for you.