Google

segunda-feira, maio 05, 2008

Criando Componentes com Estilos Personalizáveis

No post anterior foi relatado em detalhes a definição, a diferença e como gerar temas e estilos compilados usando o Flex Builder e o prompt de comando pelo compilador. Agora será explicado como adicionar propriedades personalizadas de estilo aos componentes.

Vamos tomar como base, o componente de pesquisa. Ele é composto por um label, um campo de código, uma imagem (que chama a ação de abrir a tela de pesquisa) e mais um campo de texto (com a descrição do código do campo anterior). Veja a imagem abaixo:

Este componente estende um VBox, adicionando um Label, um TextInput, uma Image e mais um TextInput. A imagem acima é a apresentação padrão deste componente. No entanto, poderíamos criar um tema no qual a imagem da ação de abrir a tela de pesquisa fosse outra. Poderíamos também, dar enfoque ao campo de código, ao invés do campo de descrição, deixando-o maior. Essas são algumas propriedades passíveis de estar num seletor CSS. Veja algumas alternativas para este componente:

Ou,
Propriedades como x, y, width e height são propriedades do UIComponent, não estilos. E por esse motivo não podem ser setados através de CSS, em tese. Digo em tese, pois podemos simular, usando algum método de invalidate e seu respectivo tratamento no render posterior.

Há três passos para criar os estilos personalizáveis:

  1. Na classe MXML ou no arquivo .as do componente, colocar a meta informação do estilo;
  2. Definir os valores padrão das propriedades de estilo que estão sendo criadas;
  3. Sobrescrever o médoto styleChanged.

Vejamos a seguir os detalhes de cada passo.

Primeiro Passo: Style metadata tag
Devemos usar a tag [Style] antes da definição de classe, num arquivo .as, ou dentro do bloco <mx:metadata>, de um MXML. A sintaxe dessa tag é a seguinte:

[Style(name="style_name"[,property="value",...])]

Veja abaixo a descrição das propriedades da tag [Style], conforme o guia de desenvolvimento da Adobe:

Seguindo nosso exemplo com o componente de pesquisa, devemos adicionar as seguintes tags:

[Style(name="searchIcon", type="Class", inherit="no")]
[Style(name="disabledSearchIcon", type="Class", inherit="no")]
[Style(name="inputCodeWidth", type="Number", inherit="no")]

Segundo Passo: Valores padrão das propriedades
Vamos definir três propriedades de classe que conterão os valores (inclusive o padrão) dos estilos. Veja:

[Embed(source="assets/img/search.png")] private var _searchImg:Class;
[Embed(source="assets/img/search_dis.png")] private var _searchImgDisabled:Class;
private var _inputCodeWidth:Number = 80;

Como são propriedades privadas, devemos criar os métodos get e set, conforme abaixo:

public function get searchImg():Class { return _searchImg; }
public function get searchImgDisabled():Class { return _searchImgDisabled; }
public function get inputCodeWidth():Number { return _ inputCodeWidth; }

public function set searchImg(searchImg:Class):void {
_searchImg = searchImg;
}
public function set searchImgDisabled(searchImgDisabled:Class):void {
_searchImgDisabled = searchImgDisabled;
}
public function set inputCodeWidth(inputCodeWidth:Number):void {
_inputCodeWidth = inputCodeWidth;
}

Devemos usar essas propriedades na criação dos filhos ou nos métodos correspondentes aos invalidates. Isso servirá para deixar nosso componente com uma aparência agradável mesmo quando não se usar estilos. É como se fosse um Hallo Theme, comparando-se com o que acontece no Flex.

Terceiro Passo: Sobrescrever o método styleChanged
Após definir o padrão, devemos sobrescrever o método styleChanged. Assim, podemos pegar as propriedades setadas na defnição do estilo, esteja ela onde estiver (num arquivo CSS, no corpo do documento ou inline). Veja abaixo:

override public function styleChanged(styleProp:String):void {
super.styleChanged(styleProp);

var searchIconStyle:Class = getStyle("searchIcon");
var disabledSearchIconStyle:Class = getStyle("disabledSearchIcon");
var inputCodeWidthStyle:Number = Number(getStyle("inputCodeWidth"));

if(searchIconStyle != null){
_searchImg = searchIconStyle;
}

if(disabledSearchIconStyle != null){
_searchImgDisabled = disabledSearchIconStyle;
}

if(!isNaN(inputCodeWidthStyle)){
_inputCodeWidth = inputCodeWidthStyle;
}
}

Neste método armazenamos o estilo recolhido pelo getStyle e testamos se ele existe antes de substituir aquela propriedade padrão, definida no primeiro passo. Aqui, se necessário, nós podemos chamar o invalidateDisplayList com alguma flag. Assim, no updateDisplayList, fazemos as construções necessárias. Por exemplo, a construção de um traço, via CSS: Verificamos se o usuário quer construir o traço (através de uma propriedade CSS). Caso positivo, setamos uma flag e chamamos o invalidateDisplayList. No updateDisplayList, verificamos esta flag e construímos o traço. A forma como construir o traço pode variar desde a simples utilização do HRule ou VRule até por meio do objeto graphics.

Fazendo uso destas definições e aplicando os conceitos de temas e CSS, discutidos no post anterior, a personalização de uma aplicação Flex torna-se bem fácil!

Boa semana!