1

我有一个具有自定义外观的 Spark ButtonBar,它为“middleButton”需求定义了一个自定义外观。我的CustomButtonBarSkin有一个自定义状态,minimized,我想将它传递到我的 middleButton 皮肤中,以便它可以修改其设计。

是否有可能做到这一点?我可以看到我的按钮皮肤可以使用 parentDocument.currentState 来获得最小化状态,但这真的很难看。有什么方法可以将皮肤从栏传递到子按钮?

4

4 回答 4

2

我认为你应该扩展 default ButtonBar。像这样的东西:

package
{
import mx.core.IFactory;

import spark.components.ButtonBar;

[SkinState("minimized")]
[SkinState("minimizedDisabled")]
public class MinimizableButtonBar extends ButtonBar
{
    public function MinimizableButtonBar()
    {
        super();

        itemRendererFunction = defaultButtonBarItemRendererFunction;
    }

    [SkinPart(required="true", type="mx.core.IVisualElement")]
    public var middleButtonMinimized:IFactory;

    private var _minimized:Boolean;

    [Bindable]
    public function get minimized():Boolean
    {
        return _minimized;
    }

    public function set minimized(value:Boolean):void
    {
        if (_minimized == value)
            return;

        _minimized = value;
        invalidateSkinState();
        itemRendererFunction = defaultButtonBarItemRendererFunction;
    }

    override protected function getCurrentSkinState():String
    {
        if (_minimized)
            return enabled ? "minimized" : "minimizedDisabled";
        return super.getCurrentSkinState();
    }

    private function defaultButtonBarItemRendererFunction(data:Object):IFactory
    {
        var i:int = dataProvider.getItemIndex(data);
        if (i == 0)
            return firstButton ? firstButton : (_minimized ? middleButtonMinimized : middleButton);

        var n:int = dataProvider.length - 1;
        if (i == n)
            return lastButton ? lastButton : (_minimized ? middleButtonMinimized : middleButton);

        return (_minimized ? middleButtonMinimized : middleButton);
    }
}
}

因此,使用此代码,您可以通过以下方式声明您的自定义皮肤:

<?xml version="1.0" encoding="utf-8"?>
<s:Skin alpha.disabledGroup="0.5" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
    <fx:Metadata>[HostComponent("MinimizableButtonBar")]</fx:Metadata>

    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" stateGroups="disabledGroup" />
        <s:State name="minimized" stateGroups="minimizedGroup" />
        <s:State name="minimizedDisabled" stateGroups="disabledGroup,minimizedGroup" />
    </s:states>

    <fx:Declarations>
        <fx:Component id="firstButton">
            <s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarFirstButtonSkin" />
        </fx:Component>
        <fx:Component id="middleButton">
            <s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarMiddleButtonSkin" />
        </fx:Component>
        <fx:Component id="middleButtonMinimized">
            <s:ButtonBarButton skinClass="MinimazedButtonBarMiddleButtonSkin" />
        </fx:Component>
        <fx:Component id="lastButton">
            <s:ButtonBarButton skinClass="spark.skins.spark.ButtonBarLastButtonSkin" />
        </fx:Component>
    </fx:Declarations>

    <s:DataGroup height="100%" id="dataGroup" width="100%">
        <s:layout>
            <s:ButtonBarHorizontalLayout gap="-1" />
        </s:layout>
        <s:layout.minimizedGroup>
            <s:VerticalLayout />
        </s:layout.minimizedGroup>
    </s:DataGroup>
</s:Skin>

希望这能解决您的问题。

如果您的最小化状态只是关于更改中间按钮皮肤,您可以从自定义组件和皮肤中删除所有与状态相关的代码。

于 2011-04-16T14:45:54.937 回答
0

我最近正在处理按钮栏的皮肤,并希望扩展/删除一些默认行为。我没有扩展和覆盖或复制/粘贴 ButtonBar 代码,而是推出了我自己的简约组件:。

public class HButtonBarGroup extends HGroup {

    public function HButtonBarGroup() {
        addEventListener(ElementExistenceEvent.ELEMENT_ADD, refreshSkins);
        super();
        gap = -1;
    }

    private function refreshSkins(event : * = null) : void {
        var buttonCount : int = numElements;

        for (var i : int = 0; i < buttonCount; i++) {
            var button : Button = getElementAt(i) as Button;
            var skinClass : Class

            if ((buttonCount == 0) || (buttonCount > 2 && (i != 0 && i != buttonCount)))
                skinClass = GreyButtonBarMiddleButtonSkin;
            else if (i == 0)
                skinClass = GreyButtonBarFirstButtonSkin;
            else
                skinClass = GreyButtonBarLastButtonSkin;

            Button(getElementAt(i)).setStyle("skinClass", skinClass);
        }
    }
}

这将使您能够做任何您想做的事情,而不必在 ButtonBar、ButtonBarBase 和 ButtonBarSkin 周围踮脚——除非您想要切换按钮/选定索引,否则所有这些都是不必要的。IMO 基于 dataProvider 创建按钮而不是仅仅在 MXML 中声明按钮并在那里分配处理程序和其他属性是很痛苦的。

于 2011-04-16T06:10:51.350 回答
0

我最近需要根据其父状态更改组件上的皮肤。我使用了与 HTML 相同的解决方案,使用 CSS。在您的情况下,类似于:

s|ButtonBar:minimized s|ButtonBarButton {
    skinClass: ClassReference("CustomButtonBarSkin");
}
s|ButtonBarButton {
    skinClass: ClassReference("spark.skins.spark.ButtonBarMiddleButtonSkin");
}

:minimized伪选择器(用于状态)。

不幸的是,这似乎并没有被孩子(错误?)捡起,除非我在状态更改时更改了父元素上的 styleName:

<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"
    styleName.normal="foo" styleName.minimized="foo"
    >

也许有一些无效的方法我应该呼吁父母改变状态而不是让孩子接受改变,但只需将 styleName 更改为虚假的东西就可以了。

这可能不是 Flex 中广泛使用的技术,因为 Flex 3 仅支持基本的 CSS 选择器。

于 2011-04-16T18:07:42.453 回答
0

也许我没有得到你想要做的事情,但这对我来说似乎相当明显和容易。当最小化状态处于活动状态时,只需让您的自定义按钮栏皮肤设置中间按钮的状态:

<s:Skin>

<s:states>
<s:State name="minimized" />
</s:states>

<s:ButtonBarButton currentState.minimized="someState" />

</s:Skin>

得到它?

于 2011-04-16T19:44:28.757 回答