Flex/ Flex 4/ Flex 4.5

Flex comunicando com o Skins

É possível fazer isso no mundo de duas formas, sendo um super herói ou sendo um framework do Flex. 😀

Criar skins é maravilhoso no Flex, você faz seu sistema ganhar vida, uma vida não só fantástica mais uma vida dinamica. Alguns tem dúvidas quanto e como fazer isso fluir de forma simples.

A explicação mais clara e objetiva que eu posso dar é : Veja o Camaleão. Sua pele é altamente camuflável e adaptada a qualquer terreno. Skins no Flex é justamente isso, adaptar o feio em bonito. Embora o camaleão continue feio, mudando só sua cor.

Vejamos o exemplo vivo abaixo

Requer o Flash Player

Agora veja como é feito, eu crio um novo Skin no Flash Builder com as seguintes caracteristicas.

Arquivo MySkin.mxml

<?xml version="1.0" encoding="utf-8"?>
 
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled="0.5">
 
    <fx:Metadata>
    <![CDATA[
        /**
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("MyContainer")]
    ]]>
    </fx:Metadata>
 
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
 
    <!--- Defines the appearance of the SkinnableContainer class's background. -->
    <s:Ellipse width="{hostComponent.raio}" height="{hostComponent.raio}" id="background" verticalCenter="0" horizontalCenter="0">
        <s:fill>
            <!--- @private -->
            <s:SolidColor id="bgFill" color="{hostComponent.color}"/>
        </s:fill>
    </s:Ellipse>
 
    <!--
        Note: setting the minimum size to 0 here so that changes to the host component's
        size will not be thwarted by this skin part's minimum size.   This is a compromise,
        more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
    -->
    <!--- @copy spark.components.SkinnableContainer#contentGroup -->
    <s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" minWidth="0" minHeight="0">
        <s:layout>
            <s:BasicLayout/>
        </s:layout>
    </s:Group>
 
</s:Skin>

A comunicação do skin com o componente que vai usa-lo, se dá pela palavrinha reservada hostComponent, veja que no meu tag Ellipse, eu uso ele para mudar a largura e altura usando a propriedade raio que é uma propriedade do componente que eu tenho e irei usar.

Outro detalhe é que esse skin eu seto quem será o host, ou seja quem hospedará ele.

   <fx:Metadata>
    <![CDATA[
        /**
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("MyContainer")]
    ]]>
    </fx:Metadata>

No Caso eu tenho o componente MyContainer

Que tem o seguinte código:

Arquivo MyContainer.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
					  xmlns:s="library://ns.adobe.com/flex/spark"
					  xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300"
					  skinClass="MySkin">
	<s:layout>
		<s:BasicLayout/>
	</s:layout>
	<fx:Script>
		<![CDATA[
 
 
			[Bindable]private var _color:uint = 0x000000;
			[Bindable]private var _raio:Number = 100;
 
 
			[Bindable]
			public function get raio():Number
			{
				return _raio;
			}
 
			public function set raio(value:Number):void
			{
				_raio = value;
			}
 
			[Bindable]
			public function get color():uint
			{
				return _color;
			}
 
			public function set color(value:uint):void
			{
				_color = value;
			}
 
		]]>
	</fx:Script>
</s:SkinnableContainer>

E para usar basta eu arrastar meu Container para tela e setar via CSS ou até mesmo direto no container a propriedade skinClass.

<s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
					  xmlns:s="library://ns.adobe.com/flex/spark"
					  xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300"
					  skinClass="MySkin">

E aqui é o código de App que você viu lá em cima.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   xmlns:ns1="*"
			   width="385" height="340" minWidth="955" minHeight="600">
 
	<fx:Script>
		<![CDATA[
			protected function changeMyCompInnerSize(event:Event):void
			{
				MyComp.raio = radioChanger.value;
			}
		]]>
	</fx:Script>
 
	<s:HSlider id="radioChanger" x="143" y="303"
			   change="changeMyCompInnerSize(event)" maximum="500" minimum="10"
			   stepSize="1"/>
 
	<ns1:MyContainer color="#84C239" id="MyComp" x="59" y="35" width="265" height="229">
		<s:Label text="hello World" verticalCenter="0" horizontalCenter="0"/>
	</ns1:MyContainer>
 
</s:Application>

Fácil não? Os skins realmente são salvadores da pátria, você consegue absorver muita e transformar o que era complexo em simples. Vejamos outro exemplo abaixo.

Nesse exemplo eu usei de forma bem simples o Gauge Chart , uma pequena demonstração de como Skins podem nos ajudar e muito, principalmente criar gráficos.

Requer o Flash Player

Aqui abaixo você ver o código fonte da App de cima.

 
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   xmlns:ns1="*"
			   width="581" height="362" minWidth="955" minHeight="600">
 
	<fx:Script>
		<![CDATA[
			protected function mudarValor(event:Event):void
			{
				// TODO Auto-generated method stub
				grafico.value = valorChanger.value;
			}
 
			protected function mudarPressao(event:Event):void
			{
				// TODO Auto-generated method stub
				pressaoChart.value = pressaoValor.value;
			}
 
		]]>
	</fx:Script>
 
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<ns1:MyGauge id="grafico" x="30" y="70" width="240" height="240">
	</ns1:MyGauge>
	<s:HSlider id="valorChanger" x="108" y="330" change="mudarValor(event)" maximum="360" minimum="0"
			   stepSize="1" value="90"/>
	<s:HSlider id="pressaoValor" x="399" y="331" change="mudarPressao(event)" maximum="360" minimum="0"
			   stepSize="1" value="90"/>
	<s:Label x="321" y="330" text="Valor"/>
	<s:Label x="30" y="329" text="Valor"/>
	<s:Label x="39" y="41" fontSize="22" text="Análise do Dosador"/>
	<s:Label x="313" y="40" fontSize="22" text="Pressão no catalizador"/>
	<ns1:MyGauge value="220" fillColors="{[0xe70505,0xb40909]}" id="pressaoChart" x="301" y="70" width="240" height="240">
	</ns1:MyGauge>
</s:Application>

O Componente MyGaugue.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:SkinnableContainer skinClass="GaugeSkin" xmlns:fx="http://ns.adobe.com/mxml/2009"
					  xmlns:s="library://ns.adobe.com/flex/spark"
					  xmlns:mx="library://ns.adobe.com/flex/mx" >
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
 
			[Bindable]private var _value:Number = 90;
			[Bindable]private var _ponteiroColor:uint = 0x000000;
			[Bindable]private var _fillColors:Array = [0x6FC9FF,0x5380D0];
 
 
 
			[Bindable]
			public function get fillColors():Array
			{
				return _fillColors;
			}
 
			public function set fillColors(value:Array):void
			{
				_fillColors = value;
			}
 
			[Bindable]
			public function get ponteiroColor():uint
			{
				return _ponteiroColor;
			}
 
			public function set ponteiroColor(value:uint):void
			{
				_ponteiroColor = value;
			}
 
			[Bindable]
			public function get value():Number
			{
				return _value;
			}
 
			public function set value(value:Number):void
			{
				_value = value;
			}
 
		]]>
	</fx:Script>
</s:SkinnableContainer>

E finalmente o código do GaugeSkin.xml

<?xml version="1.0" encoding="utf-8"?>
 
<!--
 
    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.
 
    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.
 
-->
 
<!--- The default skin class for a Spark SkinnableContainer container.
 
     @see spark.components.SkinnableContainer
 
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled="0.5">
 
    <fx:Metadata>
    <![CDATA[
        /**
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("MyGauge")]
    ]]>
    </fx:Metadata>
 
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
 
    <!--- Defines the appearance of the SkinnableContainer class's background. -->
	<s:Group width="100%" height="100%">
 
 
	<s:Ellipse width="100%" height="100%">
		<s:fill>
			<s:LinearGradient rotation="90">
				<s:GradientEntry alpha="1.0" color="{hostComponent.fillColors[0]}" ratio="0"/>
				<s:GradientEntry alpha="1.0" color="{hostComponent.fillColors[1]}" ratio="1"/>
			</s:LinearGradient>
		</s:fill>
	</s:Ellipse>
	<s:Rect x="{Math.ceil(hostComponent.width*0.5)}" y="0" width="10" height="{hostComponent.width/2}"
			rotation="{hostComponent.value}" transformX="5"
			transformY="{Math.ceil(hostComponent.width*0.5)}">
		<s:fill>
			<s:SolidColor color="{hostComponent.ponteiroColor}"/>
		</s:fill>
	</s:Rect>
	<s:RichText  horizontalCenter="0" y="30" color="#ffffff" fontFamily="Arial" fontSize="14" fontWeight="bold"
				tabStops="S0 S50" text="{hostComponent.value}"/>
	</s:Group>
    <!--
        Note: setting the minimum size to 0 here so that changes to the host component's
        size will not be thwarted by this skin part's minimum size.   This is a compromise,
        more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
    -->
    <!--- @copy spark.components.SkinnableContainer#contentGroup -->
    <s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" minWidth="0" minHeight="0">
        <s:layout>
            <s:BasicLayout/>
        </s:layout>
    </s:Group>
 
</s:Skin>

Até a próxima e bons estudos com Skins.

2 thoughts on “Flex comunicando com o Skins

  1. Boa Tarde Igor!
    Neste seu exemplo você se comunicou do Skin para o componente. Mas e o contrário?
    Bem, no meu caso eu gostaria de mudar o State do Skin.
    Este Skin eu usei como base o Skin padrão do componente.
    Tentei usar:
    setCurrentState(“search”);
    e
    skin.setCurrentState(“search”);
    invalidateSkinState();

    mas nenhum funcionou.

  2. @Alexandre De Carli

    Deixe o componente controlando o skin:

    * Declare os states no componente(mx.states);
    * Use metadata no componente para obrigar o skin a ter os states.
    * Modifique o state no componente;
    * No skin utilize currentState=”{hostComponent.currentState}”;

    Eu utilizo assim.

    Abraço.

Deixe uma resposta

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