When the existing components provided by Flutter cannot meet our needs, or we need to encapsulate some common components in order to share code, then we need custom components. There are three ways to customize components in Flutter: by combining other components, self-drawing, and implementing RenderObject. In this section we first introduce the characteristics of these three methods respectively, and the details of them will be introduced in detail in the following chapters.
In this way, other components are assembled to form a new component. For example, we introduced earlier Containeris a combination of components, it is composed of DecoratedBox, ConstrainedBox, Transform, Padding, Alignand other components.
In Flutter, the idea of combination is very important. Flutter provides a lot of basic components, and our interface development is actually combining these components as needed to achieve various layouts.
If we can’t achieve the required UI through existing components, we can do it by self-drawing components. For example, we need a circular progress bar with a gradual color gradient, and Flutter CircularProgressIndicatordoes not support displaying precise progress. When applying a gradient color to the progress bar (its valueColorproperty only supports changing the color of the Indicator when performing a rotation animation), the best way at this time is to draw the desired appearance through custom components. We can implement UI self-drawing through the CustomPaintsum provided in Flutter Canvas.
UI component itself has the appearance of a Flutter offered, such as text Text, Imageare through the corresponding RenderObject(we will "Flutter core principles" described in detail in the chapter RenderObject) rendered, such as Text is RenderParagraphrendered; and Imagea is RenderImagerendered. RenderObjectIs an abstract class, it defines an abstract method paint(...):
void paint(PaintingContext context, Offset offset)
PaintingContextThe drawing context representing the component PaintingContext.canvascan be obtained through Canvas, and the drawing logic is mainly Canvasimplemented through API. Subclasses need to rewrite this method to implement their own drawing logic. If they RenderParagraphneed to implement text drawing logic, they RenderImageneed to implement picture drawing logic.
It can be found that RenderObjectin the end, it is also Canvasdrawn through API, so what is the difference between the way of implementation and RenderObjectthe way of passing CustomPaintand Canvasself-drawing described above ? In fact, the answer is very simple. It CustomPaintis just a proxy class encapsulated for the convenience of developers. It directly inherits from it SingleChildRenderObjectWidget. RenderCustomPaintThe paintmethod used is to connect Canvaswith the brush Painter(which needs to be implemented by the developer, introduced in the following chapter) to achieve the final drawing (drawing logic is Painterin) .
"Combination" is the easiest way to customize components. In any scenario where custom components are required, we should give priority to whether it can be achieved through combination. Self-drawing and implementation RenderObjectmethods are essentially the same. Developers need to call the CanvasAPI to draw the UI manually. The advantage is that it is powerful and flexible. In theory, it can realize any appearance of the UI. The disadvantage is that you must understand the Canvasdetails of the API and have to do it yourself. To implement the drawing logic.
In the next section of this chapter, we will introduce the process of customizing the UI in detail through some examples. Since the latter two methods are essentially the same, and many basic components in Flutter are implemented through RenderObjectthe form, we will follow up Only the method of CustomPaintsum is introduced Canvas. If readers RenderObjectare curious about the custom method, they can check RenderObjectthe implementation source code corresponding to the relevant basic components in Flutter , such as RenderParagraphor RenderImage.