Question

I have a ToggleButton with an icon and a mobile skin.

   <s:ToggleButton icon="@Embed('/assets/myIcon.png')" skinClass="skins.mobile.ToggleButtonSkin "/>

Here is the skin.

package skins.mobile
{   
    import flash.display.DisplayObject;
    import flash.display.Sprite;

    import mx.core.DPIClassification;
    import mx.core.mx_internal;
    import mx.events.FlexEvent;

    import spark.components.supportClasses.StyleableTextField;
    import spark.skins.mobile.supportClasses.ButtonSkinBase;

    import assets.themes.joy.embed.fxg.MobileButtonDownSkin;
    import assets.themes.joy.embed.fxg.MobileButtonUpSkin;
    import assets.themes.joy.embed.fxg.MobileSelectedButtonUpSkin;

    use namespace mx_internal;

    public class ToggleButtonSkin extends ButtonSkinBase
    {       
        public function ToggleButtonSkin()
        {
            super();

            // replace FXG asset classes
            upBorderSkin = MobileButtonUpSkin;
            downBorderSkin = MobileButtonDownSkin;
            upAndSelectedBorderSkin = MobileSelectedButtonUpSkin;
            downAndSelectedBorderSkin = MobileSelectedButtonUpSkin;

            //default width/height
            measuredDefaultHeight = 66;
            measuredDefaultWidth = 208;

            layoutGap = 7;
        }

        //--------------------------------------------------------------------------
        //
        //  Variables
        //
        //--------------------------------------------------------------------------        
        private var _border:DisplayObject;

        private var changeFXGSkin:Boolean = false;

        private var borderClass:Class;

        private var _downStateFlag:Boolean;

        /**
         *  Read-only button border graphic. Use getBorderClassForCurrentState()
         *  to specify a graphic per-state.
         * 
         *  @see #getBorderClassForCurrentState()
         */
        protected function get border():DisplayObject
        {
            return _border;
        }

        //--------------------------------------------------------------------------
        //
        //  Properties
        //
        //--------------------------------------------------------------------------

        /**
         *  Class to use for the border in the up state.
         */  
        protected var upBorderSkin:Class;

        /**
         *  Class to use for the border in the down state.
         */ 
        protected var downBorderSkin:Class; 

        /**
         *  Class to use for the border when selected in the up state.
         */  
        protected var upAndSelectedBorderSkin:Class;

        /**
         *  Class to use for the border when selected in the down state.
         */  
        protected var downAndSelectedBorderSkin:Class;

        //--------------------------------------------------------------------------
        //
        //  Overridden methods
        //
        //--------------------------------------------------------------------------

        /**
         *  @private 
         */
        override protected function commitCurrentState():void
        {   
            super.commitCurrentState();

            borderClass = getBorderClassForCurrentState();

            if (!(_border is borderClass))
                changeFXGSkin = true;

            var icon:DisplayObject = getIconDisplay();

            //reduce fontSize for down state
            if(currentState == "down") {
                icon.scaleX = icon.scaleY = .5;
                _downStateFlag = true;
            } else {
                if(_downStateFlag) {
                    icon.scaleX = icon.scaleY = 1;
                    _downStateFlag = false;
                }
            }

            // update borderClass and background
            invalidateDisplayList();
        }

        /**
         *  @private
         */
        override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.layoutContents(unscaledWidth, unscaledHeight);

            // size the FXG background
            if (changeFXGSkin)
            {
                changeFXGSkin = false;

                if (_border)
                {
                    removeChild(_border);
                    _border = null;
                }

                if (borderClass)
                {
                    _border = new borderClass();
                    addChildAt(_border, 0);
                }
            }

            layoutBorder(unscaledWidth, unscaledHeight);
        }

        /**
         *  Position the background of the skin. Override this function to re-position the background. 
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 2.5 
         *  @productversion Flex 4.5
         */ 
        mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
        {
            setElementSize(border, unscaledWidth, unscaledHeight);
            setElementPosition(border, 0, 0);
        }       

        /**
         *  Returns the borderClass to use based on the currentState.
         */
        protected function getBorderClassForCurrentState():Class
        {
            var cla:Class;
            switch(currentState)
            {
                case "down":
                    cla = downBorderSkin;
                    break;
                case "up":
                    cla = upBorderSkin;
                    break;
                case "downAndSelected":
                    cla = downAndSelectedBorderSkin;
                    break;
                case "upAndSelected":
                    cla = upAndSelectedBorderSkin;
                    break;
            }
            return cla;
        }       
    }
}

The icon is supposed to scale down when in "down" state. However, it seems that in mobile button skins, there is no iconDisplay property, so I cannot access the icon.

If you look at the commitCurrentState() function, I tried scaling with getIconDisplay() instead. But this does not work.

Does anyone know if there's a way to scale the icon?

Was it helpful?

Solution

Figured it out. Scaling needs to happen in layoutContents() instead of commitCurrentState().

Those two function should look like this:

        /**
         *  @private 
         */
        override protected function commitCurrentState():void
        {   
            super.commitCurrentState();

            borderClass = getBorderClassForCurrentState();

            if (!(_border is borderClass))
                changeFXGSkin = true;

            // update borderClass and background
            invalidateDisplayList();
        }

        /**
         *  @private
         */
        override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.layoutContents(unscaledWidth, unscaledHeight);

            // size the FXG background
            if (changeFXGSkin)
            {
                changeFXGSkin = false;

                if (_border)
                {
                    removeChild(_border);
                    _border = null;
                }

                if (borderClass)
                {
                    _border = new borderClass();
                    addChildAt(_border, 0);
                }
            }

            layoutBorder(unscaledWidth, unscaledHeight);

            //reduce icon size in "down" state
            if(currentState == "down") {                    
                var iconDisplay:DisplayObject = getIconDisplay();
                if(iconDisplay) {
                    setElementSize(iconDisplay, iconDisplay.width *.85, iconDisplay.height *.85); 
                    setElementPosition(iconDisplay, (unscaledWidth - iconDisplay.width) / 2, (unscaledHeight - iconDisplay.height) / 2);
                }
            }
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top