Flex 三态复选框

在周末挤出了一点时间,写了一个三态复选框的组件,单独使用没有价值,不过集成到树之中可以很好的实现三态树,今天上午便把三态树组件也完成了,Flex自定义组件基本无所不能,此组件基于最新的Flex4.6(也支持Apache Flex4.10,我目前已经全面升级到4.10,为了和以后保持一致),废话不表,呆毛如下:

1.首先创建一个类TriStateCheckBox,继承至CheckBox,为了实现复选框的三种状态,我需要设置三个公开的静态常量来表示,用0,1,2来分别表示Unchecked,Checked和Indeterminate三种状态:

 1 public class TriStateCheckBox extends CheckBox
 2 {
 3     public static const Unchecked:int = 0;
 4     public static const Checked:int = 1;
 5     public static const Indeterminate:int = 2;
 6         
 7     public function TriStateCheckBox()
 8     {
 9         super();
10     }
11 }


2.为组件自定义一个checkState属性,用来标识复选框的三种状态,这里需要注意的是当状态处于Checked和Indeterminate时,我们认为复选框的selected=true,因此还需要重写复选框的selected属性,实现两者之间的协调统一:

 1 private var _checkState:int;
 2 [Bindable(event="change")]
 3 [Inspectable(category="General", defaultValue="0")]
 4 public function get checkState():int
 5 {
 6     return _checkState;
 7 }
 8 public function set checkState(value:int):void
 9 {
10     if(value == _checkState)
11         return;
12             
13     _checkState = value;
14     if(_checkState==Indeterminate || _checkState==Checked)
15     {
16         _selected = true;
17     }
18     else
19     {
20         _selected = false;
21     }
22     dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
23     invalidateSkinState();
24 }
25         
26 private var _selected:Boolean;
27 [Bindable]
28 [Inspectable(category="General", defaultValue="false")]
29 override public function get selected():Boolean
30 {
31     return _selected;
32 }
33 override public function set selected(value:Boolean):void
34 {
35     if(value == selected && checkState!=Indeterminate)
36     {
37         return;
38     }
39     _selected = value;
40     _checkState = _selected?Checked:Unchecked;
41     dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
42     invalidateSkinState();
43 }


3.现在来考虑复选框的外观,我们新建一个皮肤,主机组件设为上面建立的TriStateCheckBox,然后我们就能看到CheckBox的外观代码,大概分成了两个组,一种是没有勾选的状态:up,over,down,disabled,一种是已勾选状态:upAndSelected,overAndSelected,downAndSelected,disabledAndSelected,用来呈现两种状态,现在我就需要再额外增加一种状态的呈现,所以加入四种状态即可:upAndIndeterminated,overAndIndeterminated,downAndIndeterminated,disabledAndIndeterminated:

 1 <s:states>
 2     <s:State name="up" />
 3     <s:State name="over" stateGroups="overStates" />
 4     <s:State name="down" stateGroups="downStates" />
 5     <s:State name="disabled" stateGroups="disabledStates" />
 6     <s:State name="upAndSelected" stateGroups="selectedStates" />
 7     <s:State name="overAndSelected" stateGroups="overStates, selectedStates" />
 8     <s:State name="downAndSelected" stateGroups="downStates, selectedStates" />
 9     <s:State name="disabledAndSelected" stateGroups="disabledStates, selectedStates" />
10     <s:State name="upAndIndeterminated" stateGroups="indeterminatedStates" />
11     <s:State name="overAndIndeterminated" stateGroups="overStates, indeterminatedStates" />
12     <s:State name="downAndIndeterminated" stateGroups="downStates, indeterminatedStates" />
13     <s:State name="disabledAndIndeterminated" stateGroups="disabledStates, indeterminatedStates" />
14 </s:states>


4.好了,我现在要重写组件的状态切换逻辑,以便使组件根据三种状态来切换对应的state:

 1 override protected function getCurrentSkinState():String
 2 {
 3     var state:String = super.getCurrentSkinState();
 4     if(checkState==Indeterminate)
 5     {
 6         switch(state)
 7         {
 8             case "up":
 9             case "upAndSelected":
10             {
11                 state = "upAndIndeterminated";
12                 break;
13             }
14             case "over":
15             case "overAndSelected":
16             {
17                 state = "overAndIndeterminated";
18                 break;
19             }
20             case "down":
21             case "downAndSelected":
22             {
23                 state = "downAndIndeterminated";
24                 break;
25             }
26             case "disabled":
27             case "disabledAndSelected":
28             {
29                 state = "disabledAndIndeterminated";
30                 break;
31             }
32         }
33     }
34     return state;
35 }


5.最后,只需要在外观代码中加入我想要的第三种状态的外观即可,我个人还是比较喜欢实心方块的外观,因此我打算直接绘制一个Rect填充,此处是可以自行定义的,比如你喜欢画个空心园来表示第三状态,或者画个灰色的勾,都是可以的,思想没有边界,Flex的强大只有懂的人才能体会:

1 <s:Rect left="2" top="2" right="2" bottom="2" includeIn="indeterminatedStates">
2     <s:fill>
3         <s:SolidColor id="indeterminatedMarkFill" color="0" alpha="0.8" />
4     </s:fill>
5 </s:Rect>
原文地址:https://www.cnblogs.com/niss/p/3406238.html