9 Replies Latest reply on Oct 20, 2009 10:06 AM by mewk

    How to pass variables to Skin applied with skinClass?

    lathoudero

      Hi all,

       

      I'm experimenting with new skin for a SkinnableContainer, and I would like to pass variables to that skin to dynamically change some elements.

      This is how I would like it to work, but it doesn't. Is there a way to make it work? (Or something similar... like defining new stylesheet-elements in the skin.)

       

      <s:SkinnableContainer skinClass="skins.SkinnableContainerBackground" gradient1="0xFFF000" gradient2="0x000FFF>

      <s:RichText id="rt1" width="400" height="200"  />

      </s:SkinnableContainer>

       

      Skin:

      <s:Skin xmlns:s="library://ns.adobe.com/flex/spark"
              xmlns:fx="http://ns.adobe.com/mxml/2009"
              xmlns:d="http://ns.adobe.com/fxg/2008/dt"
              xmlns:ai="http://ns.adobe.com/ai/2008"
              height="100%"
              width="590">
          <s:layout>
              <s:BasicLayout/>
          </s:layout>
          <s:states>
              <s:State name="normal"/>
              <s:State name="disabled"/>
          </s:states>
          <fx:Metadata>[HostComponent("spark.components.SkinnableContainer")]</fx:Metadata>

          <fx:Script>
              <![CDATA[
                  [Bindable] public var gradient1:uint;
                  [Bindable] public var gradient2:uint;
              ]]>
          </fx:Script>

          <s:Group top="0"
                   bottom="0"
                   left="-11"
                   right="0">
              <s:Group x="15"
                       top="0"
                       bottom="0"
                       id="kaft">
                  <!--            <s:filters>
                       <s:DropShadowFilter alpha="0.4"
                       blurX="6"
                       blurY="6"
                       distance="4.24264"
                       quality="3" />
                       </s:filters>
                  -->
                  <s:Rect width="586"
                          ai:knockout="0"
                          d:userLabel="kaft"
                          top="0"
                          bottom="0">
                      <s:fill>
                          <s:LinearGradient y="82.3125"
                                            scaleX="585.975"
                                            rotation="-0">
                              <s:GradientEntry color="{gradient1}"
                                               ratio="0.466667"/>
                              <s:GradientEntry color="{gradient2}"
                                               ratio="1"/>
                          </s:LinearGradient>
                      </s:fill>
                  </s:Rect>
              </s:Group>

          </s:Group>

          <s:Group id="contentGroup"
                   left="20"
                   right="20"
                   top="10"
                   bottom="20">

              <s:layout>
                  <s:BasicLayout/>
              </s:layout>

          </s:Group>

      </s:Skin>

        • 1. Re: How to pass variables to Skin applied with skinClass?
          mewk Level 3

          posted this earlier, but i think it went unappreciated. let me know if this works.

           

          - e

          1 person found this helpful
          • 2. Re: How to pass variables to Skin applied with skinClass?
            markusmc82

            ou can also define custom CSS styles:

             

            MySkinnableContainer.as

                [Style(name="gradientA", type="uint", format="Color", inherit="no")]
                [Style(name="gradientB", type="uint", format="Color", inherit="no")]
                public class MySkinnableContainer extends SkinnableContainer
                {
                    public function MySkinnableContainer()
                    {
                        super();
                    }
                }
            

             

            MySkinnableContainerSkin.mxml

             

            <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/halo"
                         xmlns:s="library://ns.adobe.com/flex/spark">
            
                <fx:Metadata>
                    <![CDATA[ 
                    [HostComponent("MySkinnableContainer")]
                    ]]>
                </fx:Metadata>
            
                <s:states>
                    <s:State name="normal" />
                    <s:State name="disabled" />
                </s:states>
            
                <s:Group bottom="0" left="-11" right="0" top="0">
                    <s:Group id="kaft" x="15" bottom="0" top="0">
                        <s:Rect width="586" bottom="0" top="0">
                            <s:fill>
                                <s:LinearGradient y="82.3125" scaleX="585.975" rotation="-0">
                                    <s:GradientEntry color="{getStyle('gradientA')}" ratio="0.466667" />
                                    <s:GradientEntry color="{getStyle('gradientB')}" ratio="1" />
                                </s:LinearGradient>
                            </s:fill>
                        </s:Rect>
                    </s:Group>
                </s:Group>
            
                <s:Group id="contentGroup" bottom="20" left="20" right="20" top="10" />
            
            </s:SparkSkin>
            

             

            styles.css

             

            @namespace local "*";
            
            local|MySkinnableContainer {
                gradientA: #FF0000;
                gradientB: #000FFF;
                skinClass: ClassReference("MySkinnableContainerSkin");    
            }
            

             

            main app:

             

                <fx:Style source="styles.css" />
                
                <local:MySkinnableContainer width="590" height="100%">
                    <s:RichText id="rt1" width="400" height="200" color="#000000" text="test" />
                </local:MySkinnableContainer>
            
            1 person found this helpful
            • 3. Re: How to pass variables to Skin applied with skinClass?
              lathoudero Level 1

              Thanks markusmc82, I like the CSS-option, except for creating a new class.

               

              Is it also possible to define custom CSS within the skin? So I can reduce 4 files to just 2 files, the application holding the component, and the componentskin?

               

              Something like:1) Main.mxml containing:

              <s:SkinnableContainer skinClass="skins.SkinnableContainerBackground" gradientA="0xFFF000" gradientB="0x000FFF>
              <s:RichText id="rt1" width="400" height="200"  />
              </s:SkinnableContainer>
              

              And 2) MyCustomSkin.mxml containing

              <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/halo"
                           xmlns:s="library://ns.adobe.com/flex/spark">
                  <fx:Metadata>
                      <![CDATA[
                      [HostComponent("spark.components.SkinnableContainer")]
                      ]]>
                  </fx:Metadata>
                  <fx:Script>
                      <![CDATA[
                          [Style(name="gradientA", type="uint", format="Color", inherit="no")]
                          [Style(name="gradientB", type="uint", format="Color", inherit="no")]
                          public function MySkinnableContainer() extends SkinnableContainer // This doesn't work of course, but you get the idea...
                          {
                              super();
                          }
                      ]]>
                  </fx:Script>
                  <s:states>
                      <s:State name="normal" />
                      <s:State name="disabled" />
                  </s:states>
                  <s:Group bottom="0" left="-11" right="0" top="0">
                      <s:Group id="kaft" x="15" bottom="0" top="0">
                          <s:Rect width="586" bottom="0" top="0">
                              <s:fill>
                                  <s:LinearGradient y="82.3125" scaleX="585.975" rotation="-0">
                                      <s:GradientEntry color="{getStyle('gradientA')}" ratio="0.466667" />
                                      <s:GradientEntry color="{getStyle('gradientB')}" ratio="1" />
                                  </s:LinearGradient>
                              </s:fill>
                          </s:Rect>
                      </s:Group>
                  </s:Group>
                  <s:Group id="contentGroup" bottom="20" left="20" right="20" top="10" />
              </s:SparkSkin>
              

               

              • 4. Re: How to pass variables to Skin applied with skinClass?
                lathoudero Level 1

                Thanks mewk, It works, but even better would be to create custom CSS-elements... but I don't really like creating all those extra classes to extend the functionality of a class of a class within a component with another class...

                 

                Would be cool if there's a way to create custom CSS within the custom skin.

                If not, I'll fall back to using 'bad practice' and refer to variables using 'hostComponent'

                 

                Thanks for your suggestion!

                • 5. Re: How to pass variables to Skin applied with skinClass?
                  markusmc82 Level 1

                  It seems you can write arbitrary attribute-value pairs into css descriptions:

                   

                  SkinnableContainer {
                      anything: #ffffff;
                      skinClass: ClassReference("MySkinnableContainerSkin");    
                  }
                  

                   

                  and then obtain that value within the skin using getStyle('anything'). This approach leaves you without content completion and type validation in the css file.

                  • 6. Re: How to pass variables to Skin applied with skinClass?
                    David_F57 Level 5

                    I'm not sure if hostComponent could be regarded  as 'bad practice' the ability for the skin to communicate with the component is invaluable.

                    By extending a component you gain a great deal of flexibility when skinning.

                     

                    Before Flashbuilder was available I played around a little, I just recompiled an old(about 8-9 months ago) experiment, i make no excuses for the sloppy code and aweful colors but its just another example of how easy skinning can be and the ability to be dynamic using hostcomponent

                     

                    http://gumbo.flashhub.net/test/TestSkin.html

                     

                    source on right click

                     

                    David.

                    • 7. Re: How to pass variables to Skin applied with skinClass?
                      mewk Level 3

                      @lathoudero, I don't think it's bad practice to refer to the hostComponent; you get a tightly coupled skin/component with full code hinting support. Whether, you use css or hostComponent both methods will require some link between the two classes (for markusmc82 it was skinClass: ClassReference("skins.MySkinnableContainerSkin"); ) The one draw back with using css is that you don't get code hinting on styles within the actionscript block. In either case, for me, the solution are quite elegant, resulting in a nice separation between logic and design.

                       

                      @markusmc82, thank you, thank you for this. Your code was very clean. I hadn't really been appreciating the css method (but now I do!). I think there is a way to avoid the style sheets altogether, but that it introduces code into the skin, which I'm not a big fan of.

                       

                      BTW, I took markusmc82's code and made it dynamic (see attachment).

                       

                       

                      - e

                      • 8. Re: How to pass variables to Skin applied with skinClass?
                        lathoudero Level 1

                        @markusmc82

                        Indeed it works!

                        Just having this in my Main.mxml:

                        <fx:Style>
                             @namespace s "library://ns.adobe.com/flex/spark";
                             s|SkinnableContainer {
                                  gradientA: #ffffff;
                                  gradientB: #000000;
                                  /* skinClass: ClassReference("skins.SkinnableContainerBackground"); */
                             }
                        </fx:Style>
                        
                        <s:SkinnableContainer skinClass="skins.SkinnableContainerBackground">
                        <s:RichText id="rt1" width="400" height="200"  />
                        </s:SkinnableContainer>
                        

                        And having this in my skinnable container:

                        <s:fill>
                             <s:LinearGradient y="82.3125" scaleX="585.975" rotation="-0">
                                  <s:GradientEntry color="{getStyle('gradientA')}" ratio="0.466667"/>
                                  <s:GradientEntry color="{getStyle('gradientB')}" ratio="1"/>
                             </s:LinearGradient>
                        </s:fill>
                        

                         

                        I'm able to pass stylesheet variable to my Skin!

                        Note that I'm not using the skinClass reference... It's still working.I'm not sure how this "skinClass" works..

                        I understand I've declared gradientA and gradientB for ALL SkinnableContainers, but how does skinClass: Classreference couple gradientA AND gradientB to this specific skinclass "skins.SkinnableContainerBackground"?

                        • 9. Re: How to pass variables to Skin applied with skinClass?
                          mewk Level 3

                          you don't need css at all (not even pasted into the main app). just do the following:

                          <classes:MySkinnableContainer id="myBox" width="400" height="400"
                               skinClass="skins.MySkinnableContainerSkin"
                               gradientA="blue" gradientB="red" />
                          

                           

                          - e