Flex:如何使用火花皮肤控制TabBarButton的鼠标悬停颜色?

时间:2010-09-17 20:34:12

标签: flex

我正在尝试使用一个火花标签栏来选择一个不会在鼠标悬停时更改颜色的标签。我试图通过使用基于皮肤spark.skins.spark.TabBarButtonSkin的皮肤来实现这一点,但是尽管关闭了所选状态和overAndSelected状态的阴影,它仍然在鼠标悬停时显示深色。

这是相关的皮肤:

<?xml version="1.0" encoding="utf-8"?>

<s:SparkSkin 
xmlns:fx="http://ns.adobe.com/mxml/2009" 
xmlns:s="library://ns.adobe.com/flex/spark" 
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" 
minWidth="21" minHeight="21" alpha.disabledStates="0.5">
<fx:Metadata>[HostComponent("spark.components.ButtonBarButton")]</fx:Metadata>
<!-- host component -->
<fx:Script fb:purpose="styling" >

    import spark.components.TabBar;

    static private const exclusions:Array = ["labelDisplay"];

    /** 
     * @private
     */     
    override public function get colorizeExclusions():Array {return exclusions;}

    /**
     * @private
     */
    override protected function initializationComplete():void
    {
        useChromeColor = true;
        super.initializationComplete();
    }

    private var cornerRadius:Number = 4

    /**
     *  @private
     *  The borderTop s:Path is just a s:Rect with the bottom edge left out.
     *  Given the rounded corners per the cornerRadius style, the result is 
     *  roughly an inverted U with the specified width, height, and cornerRadius.
     * 
     *  Circular arcs are drawn with two curves per flash.display.Graphics.GraphicsUtil.
    */        
    private function updateBorderTop(width:Number, height:Number):void
    {
        var path:String = createPathData(true);
        borderTop.data = path;
    }

    /**
     *  @private
     *  Draw the selected highlight strokes.  The highlight is the same shape as the tab's
     *  border and is inset just within the border.   It must be rendererd with three separate paths, 
     *  since the top leg is rendered with two horizontal lines, with different stroke 
     *  alpha values, and the left and right vertical legs are rendered with a third alpha value.
     *  
     *  Circular arcs are drawn with two curves per flash.display.Graphics.GraphicsUtil.
     */    
    private function updateSelectedHighlight(width:Number, height:Number):void
    {
        if (!selectedHighlightV)
            return;

        var left:Number = -0.5;  // assuming stroke weight is 1.0
        var right:Number = width - 0.5;

        var path:String = createPathData(false);
        selectedHighlightV.data = path;

        // Configure the left/right sides of the two horizontal lines, defined with
        // s:Rects, that appear at the top of the selected highlight.

        selectedHighlightH1.x = selectedHighlightH2.x = left + cornerRadius;
        selectedHighlightH1.width = selectedHighlightH2.width = (right - left) - (2 * cornerRadius);            
    }  

    /**
     *  @private
     *  This function creates the path data used by borderTop and selectedHighlight.
     */
    private function createPathData(isBorder:Boolean):String
    {
        var left:Number = -0.5;  // assuming stroke weight is 1.0
        var right:Number = width - 0.5;
        var top:Number = 0.5;
        var bottom:Number = height;

        var a:Number = cornerRadius * 0.292893218813453;
        var s:Number = cornerRadius * 0.585786437626905;

        // If the path is for the highlight,
        // Draw the vertical part of the selected tab highlight that's rendered 
        // with alpha=0.07.  The s:Path is configured to include only the left and 
        // right edges of an s:Rect, along with the top left,right rounded corners. 
        // Otherwise, we draw a full path.
        var path:String = "";
        path +=  "M " + left + " " + bottom;
        path += " L " + left + " " + (top + cornerRadius);
        path += " Q " + left + " " + (top + s) + " " + (left + a) + " " + (top + a);
        path += " Q " + (left + s) + " " + top + " " + (left + cornerRadius) + " " + top;

        if (isBorder)
            path += " L " + (right - cornerRadius) + " " + top;
        else
            path += " M " + (right - cornerRadius) + " " + top;

        path += " Q " + (right - s) + " " + top + " " + (right - a) + " " + (top + a);
        path += " Q " + right + " " + (top + s) + " " + right + " " + (top + cornerRadius);
        path += " L " + right + " " + bottom;

        return path;
    }

    /**
     *  @private
     *  The cornerRadius style is specified by the TabBar, not the button itself.   
     * 
     *  Rather than bind the corner radius properties of the s:Rect's in the markup 
     *  below to hostComponent.owner.getStyle("cornerRadius"), we reset them here, 
     *  each time a change in the value of the style is detected.  Note that each 
     *  corner radius property is explicitly initialized to the default value of 
     *  the style; the initial value of the private cornerRadius property.
     */
    private function updateCornerRadius():void
    {
        var cr:Number = getStyle("cornerRadius");
        if (cornerRadius != cr)
        {
            cornerRadius = cr;
            fill.topLeftRadiusX = cornerRadius;
            fill.topRightRadiusX = cornerRadius;
            lowlight.topLeftRadiusX = cornerRadius;
            lowlight.topRightRadiusX = cornerRadius;
            highlight.topLeftRadiusX = cornerRadius;
            highlight.topRightRadiusX = cornerRadius;
            highlightStroke.topLeftRadiusX = cornerRadius;
            highlightStroke.topRightRadiusX = cornerRadius;
        }
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaleHeight:Number):void
    {
        updateCornerRadius();
        updateSelectedHighlight(unscaledWidth, unscaledHeight);
        updateBorderTop(unscaledWidth, unscaledHeight);
        super.updateDisplayList(unscaledWidth, unscaledHeight);
    }
</fx:Script>

<!-- states -->
<s:states>
    <s:State name="up" />
    <s:State name="over" stateGroups="overStates" />
    <s:State name="down" stateGroups="downStates" />
    <s:State name="disabled" stateGroups="disabledStates" />
    <s:State name="upAndSelected" stateGroups="selectedStates, selectedUpStates" />
    <s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
    <s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
    <s:State name="disabledAndSelected" stateGroups="selectedUpStates, disabledStates, selectedStates" />
</s:states>

<!--- layer 2: fill @private-->
<s:Rect id="fill" left="1" right="1" top="1" bottom="1" topLeftRadiusX="4" topRightRadiusX="4" width="69" height="21">
    <s:fill>
        <s:LinearGradient rotation="90">
            <s:GradientEntry color="0xFFFFFF" 
                             color.selectedStates="0xFFFFFF"
                             color.over="0xBBBDBD" 
                             color.down="0xAAAAAA" 
                             alpha="0.85" 
                             alpha.overAndSelected="1" />
            <s:GradientEntry color="0xD8D8D8" 
                             color.selectedStates="0xFFFFFF"
                             color.over="0x9FA0A1" 
                             color.down="0x929496" 
                             alpha="0.85"
                             alpha.overAndSelected="1" />
        </s:LinearGradient>
    </s:fill>
</s:Rect>

<!--- layer 3: fill lowlight @private-->
<s:Rect id="lowlight" left="1" right="1" top="1" bottom="1" topLeftRadiusX="4" topRightRadiusX="4">
    <s:fill>
        <s:LinearGradient rotation="270">
            <s:GradientEntry color="0x000000" ratio="0.0" alpha="0.0627" />
            <s:GradientEntry color="0x000000" ratio="0.48" alpha="0.0099" />
            <s:GradientEntry color="0x000000" ratio="0.48001" alpha="0" />
        </s:LinearGradient>
    </s:fill>
</s:Rect>

<!--- layer 4: fill highlight @private-->
<s:Rect id="highlight" left="1" right="1" top="1" bottom="1" topLeftRadiusX="4" topRightRadiusX="4">
    <s:fill>
        <s:LinearGradient rotation="90">
            <s:GradientEntry color="0xFFFFFF"
                             ratio="0.0"
                             alpha="0.33" 
                             alpha.selectedUpStates="0.22"
                             alpha.overStates="0.0" 
                             alpha.downStates="0.12"/>
            <s:GradientEntry color="0xFFFFFF"
                             ratio="0.48"
                             alpha="0.33" 
                             alpha.selectedUpStates="0.22"
                             alpha.overStates="0.0" 
                             alpha.downStates="0.12" />
            <s:GradientEntry color="0xFFFFFF"
                             ratio="0.48001"
                             alpha="0" />
        </s:LinearGradient>
    </s:fill>
</s:Rect>
<!--- layer 5: highlight stroke (all states except down) @private -->
<s:Rect id="highlightStroke" left="1" right="1" top="1" bottom="1" topLeftRadiusX="4" topRightRadiusX="4"
        excludeFrom="downStates">
    <s:stroke>
        <s:LinearGradientStroke rotation="90" weight="1">
            <s:GradientEntry color="0xFFFFFF" alpha.overStates="0.22" alpha.selectedUpStates="0.33" />
            <s:GradientEntry color="0xD8D8D8" alpha.overStates="0.22" alpha.selectedUpStates="0.33" />
        </s:LinearGradientStroke>
    </s:stroke>
</s:Rect>

<!--- layer 6: highlight stroke, selected tab, alpha=0.0 when not selected @private -->
<s:Path id="selectedHighlightV" left="1" right="1" top="1" bottom="1" width="69" height="21">
    <s:stroke>
        <s:SolidColorStroke weight="1" color="0x000000" alpha="0.0" 
                            alpha.downStates="0.15" 
                            alpha.selectedUpStates="0.00" 
                            alpha.overAndSelected="0.00" />
    </s:stroke>
</s:Path>
<!--- @private -->
<s:Rect id="selectedHighlightH1" top="1" height="1">
    <s:fill>
        <s:SolidColor color="0x000000" alpha="0.0"
                            alpha.downStates="0.25" 
                            alpha.selectedUpStates="0.0" 
                            alpha.overAndSelected="0.0" />                                    
    </s:fill>
</s:Rect>
<!--- @private -->
<s:Rect id="selectedHighlightH2" top="2" height="1">
    <s:fill>
        <s:SolidColor color="0x000000" alpha="0.0"
                            alpha.downStates="0.15" 
                            alpha.selectedUpStates="0.0" 
                            alpha.overAndSelected="0.00" />  
    </s:fill>
</s:Rect>  

<!--- layer 7: border - put on top of the fill so it doesn't disappear when scale is less than 1 @private -->
<s:Line id="borderBottom" left="0" right="0" bottom="0" excludeFrom="selectedStates">
    <s:stroke>
        <s:SolidColorStroke weight="1" 
                            color="0x000000" 
                            color.selectedStates="0x434343"
                            alpha="0.75" 
                            alpha.down="0.85"/>
    </s:stroke>
</s:Line>
<!--- @private -->
<s:Path id="borderTop" left="0" right="0" top="0" bottom="0" width="69" height="21">
    <s:stroke>
        <s:LinearGradientStroke rotation="90" weight="1">
            <s:GradientEntry color="0x000000" 
                             alpha="0.5625"
                             alpha.down="0.6375"
                             alpha.selectedStates="0.6375" />
            <s:GradientEntry color="0x000000" 
                             alpha="0.75" 
                             alpha.down="0.85"
                             alpha.selectedStates="0.85" />
        </s:LinearGradientStroke>
    </s:stroke>
</s:Path>

<!-- layer 8: text -->
<!--- @copy spark.components.supportClasses.ButtonBase#labelDisplay -->
<s:Label id="labelDisplay"
         textAlign="center"
         verticalAlign="middle"
         maxDisplayedLines="1"
         horizontalCenter="0" verticalCenter="1"
         left="7" right="7" top="2" bottom="2">
</s:Label>

</s:SparkSkin>

1 个答案:

答案 0 :(得分:1)

  1. 您可以将遍历和覆盖的状态重命名为其他状态,并添加虚假的over和OverSend状态,没有任何意义。这是快速而又肮脏的方式。
  2. 或者将具有over和overAndSelected状态的所有属性设置为初始值。
  3. 请告诉我们。

    谢谢。