Blog Componentizando a aplicação

Componentizando a aplicação

Componentizando a aplicação post thumbnail image

Uma das técnicas que mais utilizo dentro de aplicativos móveis e quando necessário também em aplicações VCL é a: componentização. Essa técnica é simples, muito prática e abre um leque de possibilidades. Também é interessante porque melhora muito a limpeza do código-fonte, deixando parte da inteligência do software no componente, muito mais fácil de dar manutenção mais tarde.

O que é componentização?

O termo pode confundir os alunos e seguidores que podem achar que vamos criar componentes instaláveis no Delphi, que também é uma técnica bem interessante, mas não….não é isso. O que vamos abordar aqui é outra forma de componentizar nossos aplicativos e softwares.

A prática é usada por outras linguagens como React e Flutter e pode ser empregada aqui no Delphi tranquilamente, inclusive sempre foi possível. Trata-se de criar um Form ou Frame, desenhar o botão, item, card como desejar, e depois criar métodos para exportar esse “design” para onde desejamos usá-los. Em Firemonkey (FMX) a técnica é mais fácil e produtiva de ser aplicada, porém em VCL também é possível sem grandes esforços. Vamos nos focar aqui em FMX.

Por onde começar?

O primeiro grande aprendizado é que podemos adicionar qualquer objeto dentro de qualquer controle no Firemonkey, o que nos favorece bastante, diferentemente da VCL. Isso significa que podemos arrastar um Label para dentro de um Edit, um Edit para dentro de um Button e assim sucessivamente. É com essa vantagem que vamos nos beneficiar. Sabendo disso, podemos criar qualquer design, exportar e adicionar com AddObject dentro de outro objeto. Vamos fazer um exemplo bem simples pra que seja fácil entendermos a técnica.

A primeira etapa consiste em criar nosso “componente”. Crie um aplicativo novo no Delphi usando File > New > Muilti-Device Application Delphi. Salve o Form1, dê um nome a ele (sugiro FrmMain) e salve o projeto. Em seguida crie um novo form utilizando File > New > Multi-Device Form. Dê o nome de Card e a unit de uCard. Nós vamos criar um design que se parecerá muito com um Card para ser mostrado com informações diversas.

Nesse novo form, arraste um TLayout para ele e desenhe-o de forma que se pareça um Card na vertical. As dimensões recomendadas são 300px de altura por 220px de largura. Dê o nome de LytCard a esse layout. Insira um TRectangle dentro desse layout e coloque sua propriedade Align como Contents para que ocupe toda a área do retângulo. Clique duas vezes na propriedade Fill. Preencha o fundo com a cor Branca e em Stroke coloque como None, assim não teremos bordas. Também modifique as propriedades XRadius e YRadius adicionando uns 20px para que tenhamos os cantos arredondados. Agora adicione outro TLayout dentro do LytCard. Mantenha o retângulo ao fundo clicando com o botão direito nele e em seguida em Control > Send to back. Vamos usar o retângulo apenas para colorir o card.

Esse novo Layout alinhe-o ao topo pela propriedade Align e deixe sua altura em 150px, metade da altura total do card. Adicione agora um TImagem no layout novo de modo que ele fique centralizado (recomendo colocar como Client no alinhamento e 20px de margem em todos os cantos), vamos receber uma imagem nesse TImage. Na segunda metade do Card adicione um novo layout alinhado como Client. E dentro desse mais um Layout com o nome Detail. Coloque as margens (margins) desse novo layout com um espaçamento de 20px nos quatro lados.

Na parte inferior nós vamos adicionar alguns labels que vão receber informações como se fossem dados de um produto, tais como: Nome, Preço e Numeração. Imagine um Card representando um calçado a ser vendido em uma loja virtual. Por isso, adicione um total de 03 Labels todos alinhados ao Topo.

  1. Label1
    • Nome: LblNome
    • Text: Vazio
  2. Label2:
    • Nome: LblNumeracao
    • Text: Vazio
  3. Label3:
    • Nome: LblValor
    • Text: R$ 99,99

A essa altura do campeonato, já deve ter entendido que poderá mudar as propriedades e desenhar um layout interessante, com cores, negritos, e etc. Deixe sua criatividade fluir nesse ponto. Segue um exemplo de card para se inspirar.

Codificando o Card

O card componentizado só será útil se pudermos dar vida a ele, e é bem fácil fazer isso. A primeira providência que precisamos tomar é exportar o LytCard para ser usado nas telas de nosso interesse. Para isso nós vamos criar uma função que devolve a instância do LytCard. Abra então o editor de código, vá até a seção public e crie o método como abaixo:

O nome em si pode ser criado como você achar mais interessante, tal como: Novo, Add, Adicionar, como achar melhor. Eu prefiro chamar de New. Note o retorno do tipo TFMXObject. Essa é a classe que precisaremos para “importar” esse controle para dentro de outro controle ao usarmos AddObject. Pressione Control + Shift + C para que o Delphi crie o escopo da função e então codifique como abaixo:

Muito fácil. Sempre que esse método for chamado, o Layout LytCard será retornado no Result, o que significa que podemos incluir esse card dentro de qualquer outro objeto. Vejamos um teste.

Retorne ao formulário principal, adicione um Botão em qualquer parte da tela (talvez no canto esquerdo superior seja interessante) e coloque um TLayout no form ocupando quase a área toda do form. Mais ou menos como abaixo:

Troque o texto do botão se preferir como fiz no meu exemplo. A ideia aqui é simples. Vamos clicar no botão e um novo card aparecerá dentro do TLayout. Pra fazer isso precisaremos antes adicionar a unit do card no form principal, por isso abaixo do Implementation adicione a uses uCard; Esse foi o nome que dei para o form que contém o componente, caso tenha dado outro nome, coloque-o.

Agora no evento OnClick do botão vamos escrever o seguinte código:

Execute o aplicativo no Windows mesmo e clique no botão. Veja o que acontece. Muito provavelmente deva ter obtido o restultado da figura abaixo.

Muito legal não? Bom, mas temos problemas. O primeiro deles é que o card não ficou no canto superior esquerdo do TLayout, ele ficou na posição em que ele foi adicionado dentro do seu form. Outro problema é que se clicarmos novamente no botão um outro card será criado, mas sobre o primeiro, dando a impressão que não aconteceu nada. E por fim, a figura e os textos não foram alterados porque, claro, ainda não programamos eles. É isso que vamos resolver agora.

Melhorando a aparência

O posicionamento do objeto dentro do Layout do form principal podemos resolver de uma maneira bastante simples, trocando o TLayout por um TFlowLayout, que vai ajustar automaticamente os objetos. A programação do botão vai mudar levemente. Mudando apenas o nome do objeto, o restante permance igual. Faça o teste e clique várias vezes no botão. Os cards ficarão grudados, mas já vamos resolver isso.

Volte no form do Card. Cique duas vezes sobre a propriedade Fill do retângulo de fundo, em seguida em Stroke e clique em Solid, para votarmos a ter um contorno no cartão. Aproveite e mude as propriedades Margins do cartão adicionando 8px nos quatro lados, assim teremos uma margem de segurança dentro do LytCard. Já no LytCard vá na propriedade Padding, que são as margens internas do objeto, adicione os valores 8px em tudo. Isso vai dar um respiro.

Execute novamente o app. Veja.

Melhorou bastante.

Agora vamos atualizar os labels na parte inferior e depois vamos trabalhar com a imagem. Para atualizar os labels, vamos usar a técnica da programação funcional. Fica bem legal trabalhar assim. Abra o editor de código em em public vamos adicionar os seguintes métodos.

Para cada label na tela, teremos um método capaz de receber um valor e atualizar o label. Perceba um detalhe sutil: o retorno da function é a classe do form do nosso card, ou seja, TCard. Isso permite que a gente chame os métodos de forma encadeada. Pressione Control + Shift + C e vamos codificar.

Cada método precisa obrigatoriamente ter o Result := Self para que possamos encadear as funções, e o restante são as atualizações normais dos labels. Veja como o código fica.

Show de bola. Então o que fazemos é alterar o texto do label e em seguida fazer o result. Bem fácil. Agora, no formulário Main, precisamos somente alterar o código do botão para o modelo abaixo. Perceba que agora podemos chamar .Nome, .Numeracao e .Valor e passar os valores. E veja mais abaixo o resultado ao clicar no botão várias vezes.

Agora é claro, os valores vão se repetir. Esses valores poderiam vir de uma tabela do banco, então teríamos um loop simples e uma codificação muito parecida com:

Perfeito. Agora vamos fazer uma última alteração, o restante deixo pra você personalizar. Vamos alterar a imagem, beleza? Eu procurei aleatoriamente fotos de tênis na internet, peguei apenas 04 imagens. Não me preocupei muito com a aparência das fotos, o objetivo central é entender como podemos adicionar uma foto no TImage do card.

Essas fotos coloquei dentro de um TImageList no form principal. Nós faremos um loop pra criar 04 cards na tela e exibir os tênis da nossa loja virtual. Certo?

Bom, agora vá até o card e vamos adicionar um novo método function Imagem(const AImage: TBitmap): TCard;. Fácil assim. Já imaginou o código né? Vamos lá?

Pronto, agora só voltar ao formulário principal e melhorar nosso código. Como sabemos que temos 04 imagens no ImageList, vamos fazer um for I e criar valores aleatórios pra preecher os cards.

Perfeito. Explicando um pouco o código. Fizemos um for de 0 a 3 para pegar todas as imagens que estão no ImageList. Criei um randômico pra simular preços de diferentes de tênis, usamos a função RandomRange da unit System.Math do Delphi. Fizemos a mesma coisa com o ano de fabricação, simulando fabricações diferentes de tênis classicos.

As únicas alterações que fizemos no Card foram melhorar as margens entre os labels para que não ficassem encavalados e aumentamos a altura do label do nome do calçado. Olha o resultado abaixo:

Aqui clicamos duas vezes no botão para simular 08 pares de tênis disponíveis. Lembrando mais uma vez que poderíamos trazer esses dados de uma tabela no banco, o que daria ainda mais credibilidade ao exemplo. Deixarei essa etapa para o leitor fazer seus próprios testes.

O que mais podemos fazer?

Eu sei, eu sei. Deve estar pensando? Mas, e como interajo com esses cards? Como posso colocar um botão que realiza alguma operação como “Comprar” o tênis por exemplo? Vejamos se consigo te ajudar rs. É relativamente simples fazer isso, só precisamos criar uma função que receba um Evento, associar a um botão e bingo, tudo certinho. Vamos ao trabalho.

Acesse o Card, adicione um botão na parte inferior do Card e crie um método assim:

function OnClickComprar(const AEvent: TNotifyEvent: TCard;

O código será como abaixo:

Fácil de entender. Caso o método tenha recebido um evento válido, associamos ele ao evento OnClick do botão.

Agora retorne ao formulário principal. Precisamos criar o evento OnClick para ser repassado como parâmetro. Vá até a seção public e inclua o método procedure DoClickComprar(Sender: TObject); e pressione Ctrl + Shift + C pra criar o escopo. O método novo e a alteração do código do botão estão na listagem abaixo:

No código do botão adicionamos a chamada .OnClickComprar(DoClickComprar) passando pra ele o nosso novo evento. E o código desse evento apenas faz um ShowMessage. Execute a aplicação e veja o resultado.

Tenho certeza que vai me pedir para saber como identificar em “qual card” clicamos. Isso também é fácil, basta criarmos um identificador único que pode ser a chave primária da tabela ou qualquer outro identificador. Vamos adicionar isso no Card na propriedade Tag de um dos objetos, assim podemos fazer um TypeCast e descobrir qual o “dono” do botão clicado e consequentemente descobrir o ID dele.

Volte no Card e adicione uma função para receber o ID. Assim:

function ID (const AID: Integer): TCard;

Onde teremos a seguinte codificação:

Na propriedade TAG do LytCard vamos armazenar o ID. Para alimentar esse ID, retorne ao código do botão na tela principal e inclua .ID(I), assim nós vamos passar o valor de “i” para o ID, como se ele fosse a chave primária. Agora vai ficar fácil identificar.

No códido do evento DoClickComprar teremos apenas que fazer alguns Typecasts pra chegar até o “dono” do componente TButton no Card, que nesse caso é o LytCard e nele vamos acessar o ID. De posse dessa informação, ficaria fácil fazer um Select no banco, excluir o registro entre outras coisas. Modifique o código do evento conforme abaixo.

O resultado é bem interessante. Colocamos o ShowMessage mostrando o ID respectivo ao botão clicado.

É claro que há muita tarefa a ser realizada para melhorar nosso exemplo, mas creio que com essa base você será capaz de criar seus próprios componentes e seguir em frente em seus estudos.

Assista a esses dois vídeos complementares:

Conclusão

A componentização é algo extremamente benéfico pois facilita e centraliza toda inteligência do componente em um único lugar. É prático e altamente personalizável.

O que achou do conteúdo? Deixe suas perguntas e comentários abaixo.

Comunidade no Telegram

🚀Comente no campo abaixo 👇👇👇 o que achou e qual sua dúvida.

Te vejo na próxima

Adriano Santos

3 thoughts on “Componentizando a aplicação”

  1. Legal. E como retiro um item que selecionei, por exemplo, se eu selecionei um item mas me arrependi ou desisti de comprar. Como retiro da seleção?

    1. Oi Anderson,
      O botão que colocamos de teste no artigo deverá receber um evento OnClick. Nesse evento OnClick você vai precisar descobrir qual é o “pai” do botão, ou seja, em qual card esse cartão está e então fazer o RemoveObject, retirando o card de dentro do container. É assim que mostramos em nossos treinamentos. No curso Comanda Eletrônica por exemplo, mostramos como criar um monitor de cozinha, onde cada card representa uma refeição. Ao tocar no botão “Pronto”, retiramos o card do conteiner, a ideia é a mesma.

      Conheça nossos cursos de desenvolvimento mobile.

Deixe sua resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Posts Relacionados