2011-04-16 39 views
1

我有一个Spark ButtonBar,它具有自定义外观,该自定义外观为“middleButton”要求定义了自定义外观。我的CustomButtonBarSkin有一个自定义状态,最小化,我想进入我的middleButton皮肤,因此它可以修改其设计。将状态传递给Flex4按钮的子按钮

可以做到这一点吗?我可以看到,我的按钮皮肤可能使用parentDocument.currentState获取最小化状态,但这真的很难看。任何方式将皮肤从栏中传递给子按钮?

回答

2

我认为你应该扩展默认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> 

希望这能解决你的问题。

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

+0

我已经有了ButtonBar的扩展来维持最小化的状态,所以你的答案真的符合我的想法。不过,我并不知道项目渲染器函数覆盖,我认为这会做到这一点。有没有办法只有一个middleButton声明并切换皮肤,或者在这个声明的皮肤上设置一个状态? – Michael 2011-04-16 16:14:04

+0

正如你所看到的按钮表示为'IFactory'。因此,似乎没有办法以声明方式设置状态。对于只有一个声明和切换皮肤,我认为它可能与通常的List中的项目渲染器相同。只记得按钮外观是一个渲染器,'ButtonBar'是一种列表。所以你可以改变一些数据提供者的字段值来通知渲染器切换另一个状态。 – Constantiner 2011-04-16 16:23:14

+0

此解决方案的工作原理,但我不得不删除最小化中间按钮的SkinPart.required = true属性,我不知道为什么。如果我将最小化的按钮作为所需的SkinPart,我会得到一个运行时异常,指出皮肤缺少所需的部分,即使它被声明为很好 - 我知道这是因为皮肤工作正常,没有required = true,但我仍然会喜欢它是必需的部分。有关于此的任何想法? – Michael 2011-04-17 02:00:19

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); 
     } 
    } 
} 

这就给你做你最想要的东西,而不必踮起脚尖周围的按钮栏,ButtonBarBase的能力,以及ButtonBarSkin - 所有不必要的,除非你想切换按钮/的selectedIndex。 IMO根据dataProvider创建按钮是一种痛苦,而不是仅仅在MXML中声明按钮并在那里分配处理程序和其他属性。

+0

谢谢,凯文,这是一个很好的建议。如果ButtonBar扩展没有像我想要的那样工作,我会尝试类似于您在此处所建议的内容。 – Michael 2011-04-16 16:16:19

0

我最近需要根据其父母状态更改组件上的皮肤。我使用了CSS中使用的同样的解决方案。在你的情况,是这样的:

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

:最小Pseudo Selector(各国)。

不幸的是,这似乎是由孩子(错误?)得到回升没有,除非我的状态变化而变化的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选择器。

0

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

<s:Skin> 

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

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

</s:Skin> 

明白了吗?