设计自定义按钮以选择时更改字体颜色/大小的最佳方法是什么?

时间:2009-12-09 14:29:00

标签: actionscript-3 button

我想设计一个扩展Button的自定义组件,它将有两个新样式:selectedColor和selectedFontSize。这些将允许按钮在选择按钮时具有不同的文本标签颜色和字体大小。 (当我说'选中'时我的意思是选择状态,而不是被选中(鼠标按下)。

我采用的方法是扩展Button,添加两个新样式,然后覆盖selected setter,然后在原始颜色样式上使用setStyle将字体颜色更改为selectedColor(如果选择了按钮) )或颜色(如果取消选择按钮)。

为了简单起见,我在本例中使用了selectedColor,但我希望能够为selectedFontSize执行此操作。

[Style(name="selectedColor",type="uint", format="Color", inherit="no")]
[Style(name="selectedFontSize",type="Number",inherit="no")]

private var _deselectedColor:uint;
private var _selectedColor:uint;

override public function set selected(value:Boolean):void {
    super.selected = value;

    _selectedColor = getStyle("selectedColor") as uint;
    if (!_deselectedColor)
        _deselectedColor = getStyle("color") as uint;

    if (selected)
        setStyle("color",_selectedColor);
    else
        setStyle("color",_deselectedColor);
}

我正在存储原始颜色(取消选择的颜色),因为它在我setStyle("color",_deselectedColor)时被覆盖。当取消选择按钮时,我需要有一些方法来检索它。

这种方法存在许多问题。首先,第一次调用选定的setter时,在对象构造期间,尚未填充样式。所以我得到的color为0x000000,selectedColor为0x000000。一旦我在构造后手动更改按钮状态,样式就能正确读入,但到那时已经太晚了,我已经存储了错误的值。此外,我需要能够通过mxml,actionscript setStyle方法或通过css设置样式更新,无论是静态还是动态。这种方法显然不会这样做。

我也尝试重写setStylestyleChanged方法。当通过mxml初始化按钮时,setStyle在构造期间永远不会被调用,所以这是不行的。调用styleChanged,但使用null作为styleProp,而不是我需要的颜色。

专业人士如何做到这一点?

1 个答案:

答案 0 :(得分:0)

我想我现在已经有了更加优雅(并且正在工作!)的答案。

我最终在updateDisplayList()中完成了工作,因此更新将在官方更新周期中延迟,而不是在执行选定的setter时强制更新。为了确保我没有存储不正确的取消选择颜色值,我现在只在选择按钮时存储它,并在取消选择按钮时清除存储。

我也使用CSSStyleDeclaration类,正如Amarghosh建议的那样,用css和mxml来管理自定义样式的阅读。

最后,我发现的一件大事是我需要调用super.callLater(invalidateDisplayList),否则按钮只会在我滚动时更新。

发布完整的解决方案。希望这有助于其他正在钻研定制组件世界的人!

import flash.display.Graphics;
import flash.geom.Matrix;

import mx.controls.Button;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;

[Style(name="selectedColor",type="uint", format="Color", inherit="no")]
[Style(name="selectedFontSize",type="Number",inherit="no")]

public class ControlBarButton extends Button
{
    private static var classConstructed:Boolean = constructStyle(); // initialize default style properties

    public function ControlBarButton() {
        super();
    }

    private static function constructStyle():Boolean {
        var style:CSSStyleDeclaration = StyleManager.getStyleDeclaration( "ControlBarButton" );

        // check to see if there's already an existing style declaration for this class
        if (style) {
            // its possible for a style to exist without defining all of the possible styles 
            // in which case we need to check each style explicitly and set a default if needed
            if ( style.getStyle( "selectedColor" ) == undefined ) {
                style.setStyle( "selectedColor", 0xFFFFFF );
            }
            if ( style.getStyle( "selectedFontSize" ) == undefined ) {
                style.setStyle( "selectedFontSize", 12 );
            }
        }
        else { // create a default style declaration
            style = new CSSStyleDeclaration();
            style.defaultFactory = function():void {
                this.selectedColor = 0xFFFFFF;
                this.selectedFontSize = 12;
            }
            StyleManager.setStyleDeclaration( "ControlBarButton", style, true );
        }

        return true;
    }

    private var selectedColorChanged:Boolean = true;
    private var selectedFontSizeChanged:Boolean = true;
    private var selectedChanged:Boolean = true;

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

        // Check to see if style changed. 
        if (styleProp=="selectedColor") {
            selectedColorChanged=true;
            invalidateDisplayList();
            return;
        }
        if (styleProp=="selectedFontSize") {
            selectedFontSizeChanged=true;
            invalidateDisplayList();
            return;
        }
    }

    private var deselectedColorStored:Boolean = false;
    private var deselectedColorVal:uint;
    private var selectedColorVal:uint;
    private var deselectedFontSizeStored:Boolean = false;
    private var deselectedFontSizeVal:Number;
    private var selectedFontSizeVal:Number;

    override public function set selected(value:Boolean):void {
        super.selected = value;

        selectedChanged=true;
        invalidateDisplayList();
    }

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
        super.updateDisplayList(unscaledWidth, unscaledHeight);

        // selected color
        if (selectedColorChanged || selectedChanged) {
            if (selected) {
                if (!deselectedColorStored) {
                    deselectedColorVal = getStyle("color") as uint;
                    deselectedColorStored = true;
                }
                selectedColorVal = getStyle("selectedColor") as uint;
                setStyle("color",selectedColorVal);
                super.callLater(invalidateDisplayList);
            }
            else {
                if (deselectedColorStored) {
                    setStyle("color",deselectedColorVal);
                    super.callLater(invalidateDisplayList);
                    deselectedColorStored = false;
                }
            }

            selectedColorChanged=false;
        }

        // selected font size
        if (selectedFontSizeChanged || selectedChanged) {
            if (selected) {
                if (!deselectedFontSizeStored) {
                    deselectedFontSizeVal = getStyle("fontSize") as Number;
                    deselectedFontSizeStored = true;
                }
                selectedFontSizeVal = getStyle("selectedFontSize") as Number;
                setStyle("fontSize",selectedFontSizeVal);
                super.callLater(invalidateDisplayList);
            }
            else {
                if (deselectedFontSizeStored) {
                    setStyle("fontSize",deselectedFontSizeVal);
                    super.callLater(invalidateDisplayList);
                    deselectedFontSizeStored = false;
                }
            }

            selectedFontSizeChanged=false;
        }

        selectedChanged=false;
    }
}