Desenhe o que quiser com Custom Paint no Flutter
Tags: custom, paint, draw, flutter
Published: 2024-05-18 13:51:21

![](https://cdn-images-1.medium.com/max/800/1*HwzkvQYd6V_QWcTyra2aQQ.png)

Fala Devs,

Que o **Flutter** é uma poderosa ferramenta que nos traz uma gama de widgets, possibilitando a criação de layouts modernos e bonitos, isso já sabemos. Mas sabia que o Flutter também possui uma ferramenta muito legal que nos permite ter uma variedade de efeitos visuais, desde formas geométricas simples como linha, quadrado, arco, círculo, etc., até desenhos complexos e animados? Literalmente, podemos desenhar com código em nossos widgets. Estou falando do **CustomPaint**.
<a href="https://www.youtube.com/watch?v=kp14Y4uHpHs" target="_blank">
 <img src="https://img.youtube.com/vi/kp14Y4uHpHs/0.jpg" alt="Monorepo (Por Que Essa Estratégia Funciona em Grandes Empresas?) " width="240" height="180" border="10" />
</a>

### Como funciona?

Para começarmos a utilizá-lo é muito simples, basta usarmos um widget chamado **CustomPaint()**, e ele espera que passemos como parâmetro um **CustomPainter** e o tamanho que nosso painter terá.
{% gist https://gist.github.com/toshiossada/9c33baf533e87114d31c41be90dd2f3e file=custom_painter_1 %}

Nosso **painter** será uma classe que irá estender a classe **CustomPainter** e terá dois métodos principais. Um será o **shouldRepaint()**, que será o método responsável pela lógica que determina se nosso painter deve ser redesenhado ou não, semelhante ao **didUpdateWidget(**) de um **StatefulWidget**. Por hora, podemos retornar sempre **true**.

O segundo método, que é o mais importante, é o **paint()**. Aqui é onde colocaremos todas as instruções do que queremos desenhar. Neste método, temos dois parâmetros importantes: o **Size**, que é a informação do tamanho da área que teremos para realizar nosso desenho, e o **Canvas**, que é responsável por realizar o desenho dentro do nosso ‘quadro’.

Neste exemplo criamos o **Paint()**, que é o responsável por conter todas as informações da propriedade do nosso desenho (Cor, espessura de linha, etc), no caso colocamos a cor roxa e com o estilo preenchido, isso significa que quando ele fechar todos os pontos de do desenho ele irá preencher com a cor selecionada. E por fim utilizamos o **Rect.fromLTWH()** que irá desenha um retângulo a partir dos pontos de par ordenado (lembra das aulas de matemática?) que passamos, lembrando que o ponto inicial é o [0, 0] e ele vai até ponto [**largura_maxima, altura_maxima**]. Por fim utilizando o **Canvas** simplesmente mando ele desenhar no meu painter utilizando o método **drawRect()**.

![](https://cdn-images-1.medium.com/max/800/1*z0woLmp0cVQbmI6v8s5inA.png)

Também temos a opção de passar o **style** como **stroke**.

![](https://cdn-images-1.medium.com/max/800/1*7zQcYB68_nemH57eNo-mZA.png)

Desta forma ele não preencherá o interior do desenho

![](https://cdn-images-1.medium.com/max/800/1*D8nwpvFPY_URv9Wf4bH-cw.png)

### Linhas

Também podemos desenhar linhas, basta utilizarmos a classe **Path()** para informar os pontos de ligação das linhas. Primeiramente, usamos o **moveTo(0, 0)** para informar o ponto inicial do desenho, e em seguida, utilizamos o **lineTo()** para informar o par ordenado dos pontos de ligação das linhas. Por fim, instruímos o canvas a desenhar nossos Paths utilizando o **drawPath()**.
{% gist https://gist.github.com/toshiossada/89ff6fef59980ee04819d51b566cd322 file=lines %}

Como resultado teremos

![](https://cdn-images-1.medium.com/max/800/1*fZsNm_KIysBlWXuLz5L5lQ.png)

### Curvas

Ainda utilizando os Paths também conseguimos fazer curvas, a primeira forma é utilizado o **quadraticBezierTo** ele adiciona um ponto “invisível” que vai flexionar a linha naquela direção.

![](https://cdn-images-1.medium.com/max/800/1*6MkhW01KJIDQZadBnprPZg.png)

![](https://cdn-images-1.medium.com/max/800/1*N8ltzr_LdQRFRyYxhI_PfA.png)

Também temos o **cubicTo** que diferente do **quadraticBezierTo** ele adiciona dois pontos de flexão.

![](https://cdn-images-1.medium.com/max/800/1*0c5Lsh4OjKEtg_InBnjWXg.png)

![](https://cdn-images-1.medium.com/max/800/1*GZC74HbKEZ74Lgr3YK8nSw.png)

![](https://cdn-images-1.medium.com/max/800/1*1W2SS_6doi3gKw0f5How1Q.png)

No **CustomPainter** também conseguimos usar em conjunto com o **ClipPath**, suponhamos que temos 2 retângulos sobrepostos e queiramos fazer um recorte em um deles para quer aparecer os dois retângulos ocupando metade da tela com um corte personalizado

![](https://cdn-images-1.medium.com/max/800/1*9_-fu4NHl39aUQUOu-EqHQ.png)

![](https://cdn-images-1.medium.com/max/800/1*1gyOhLLwxgG3VSwtDJpsXQ.png)

Podemos adicionar o primeiro retângulo com o **drawRect()** e em seguida utilizar o **clipPath** do **Canves** passando o **Path** com as ordenadas do corte e logo em seguida adicionar o segundo retângulo.
{% gist https://gist.github.com/toshiossada/c2309ce76643287ec5e62c733fa1f78f file=page3.dart %}
Como resultado teremos

![](https://cdn-images-1.medium.com/max/800/1*BZcFYDBqMOgfkj2araw2Xw.png)

### Arcos

Lembra das aulas de Geometria? Aqui utilizaremos os conceitos aprendidos, sabemos que um círculo inteiro possui **2PI**, no **Paint** e o ponto zero fica no meio do lado direito.

![](https://cdn-images-1.medium.com/max/800/1*MX7_-YYVqzS3xTskGBpvtw.png)

E com isso conseguimos desenhar um círculo ou parte dele utilizando os conceitos de seno.

![](https://cdn-images-1.medium.com/max/800/1*CDsdiWq8uhVNWeGflJx-Nw.png)
{% gist https://gist.github.com/toshiossada/813ae788aabd55db061dee74258e64e8 file=page4.dart %}
Com esses conceitos podemos fazer um progresso circular.

![](https://cdn-images-1.medium.com/max/800/1*XaEv4ofOcLHI3H8AxTLe1g.gif)

Recebemos o progresso e o texto por parâmetro

![](https://cdn-images-1.medium.com/max/800/1*cMmMkPunDGMIaIe5Jk4PkA.png)

Em seguida utilizando o **drawArc** passando o seno inicial **3PI/2** (imagine esta imagem invertida)

![](https://cdn-images-1.medium.com/max/800/1*CDsdiWq8uhVNWeGflJx-Nw.png)

E passando o progresso como parâmetro para o **drawArc**

![](https://cdn-images-1.medium.com/max/800/1*HGPq3Dk-k5CJbB4hsKDMQA.png)

Também conseguimos pedir para o **CustomPaint** desenhar textos, utilizando o TextSpan e depois assando a posição onde ele ficará

![](https://cdn-images-1.medium.com/max/800/1*2eLkGM9txso9AIaW3evRew.png)

Legal né? Da para fazer muita coisa com **CustomPaint**, nos próximos artigos vamos trabalhar um pouco mais com eles.

Os exemplos que utilizei no artigo se encotram no meu github :)

https://github.com/toshiossada/clippath


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obcg0d2y00yddve9quky.png)


Entre em nosso discord para interagir com a comunidade: flutterbrasil.com.br