keep 'down' state for spark skin button - apache-flex

I have spark skin a button with up, down, over, and disable states in a button component to create a modular. Is there a way when the user press and hold a key, the button will remain in 'down' state?
The button component include skinclass:
<?xml version="1.0" encoding="utf-8"?>
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
skinClass="wfm.keyBtn">
</s:Button>
Spark skin:
<?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:mx="library://ns.adobe.com/flex/mx"
<fx:Metadata>
[HostComponent("spark.components.Button")]
</fx:Metadata>
<s:states>
<s:State name="up"/>
<s:State name="over"/>
<s:State name="down"/>
<s:State name="disabled"/>
</s:states>
<s:Rect width="18" height="80" height.down="83" radiusX="1">
<s:stroke>
<s:SolidColorStroke color="0xaaaaaa" weight="1"/>
</s:stroke>
<s:filters>
<s:BevelFilter
distance="0"
angle="5" angle.down="5"
highlightColor="0xbbbbbb" highlightColor.down="0xaaaaaa"
highlightAlpha="1" highlightAlpha.down="1"
shadowColor="0xaaaaaa" shadowColor.down="0xffffff"
shadowAlpha="1" shadowAlpha.down="1"
blurX="5" blurX.down="6"
blurY="5" blurY.down="6"
strength="2" strength.down="2"
type="inner"
/>
</s:filters>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xf3f3f3" color.down="0xfff963" />
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:SparkSkin>

Create a subclass of Button and tell the skin to be in the down state whenever the key you care about is down. Also, whenever you detect the key is down (or no longer down), invalidate the skin state so the skin knows to check what state it should be in:
package mypackage
{
import spark.components.Button;
public class MyButton extends Button
{
private var _isKeyDown:Boolean = false;
private function get isKeyDown():Boolean {
return _isKeyDown;
}
private function set isKeyDown(b:Boolean):void {
_isKeyDown = b;
this.invalidateSkinState();
}
// Add handlers in here to set isKeyDown to true/false appropriately
override protected function getCurrentSkinState():String {
if (isKeyDown)
return "down";
else
return super.getCurrentSkinState();
}
}
}

Related

Flex 4 bug:inherited propery cause transition bug

i try to make some foldable groups, like an accordion component
i create a Base.as class and extends from Group,code like this
package
{
import flash.events.MouseEvent;
import spark.components.Group;
public class Base extends Group
{
public var header:Group;
public var body:Group;
public function Base()
{
super();
}
override protected function initializationComplete():void
{
super.initializationComplete();
if(header)
{
header.addEventListener(MouseEvent.CLICK,changeState);
}
}
protected function changeState(event:MouseEvent):void
{
if(currentState=="fold")
currentState="unfold";
else
currentState="fold";
}
}
}
and i defined two properties,header and body here,but i don't instantiate here,and then i worte a mxml component "FoldUnit.mxml" that extends "Base" and i will instantiate header and body in it,code like this
<?xml version="1.0" encoding="utf-8"?>
<local:Base xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" currentState="fold" clipAndEnableScrolling="true"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:local="*" width="200" >
<local:states>
<s:State name="fold" />
<s:State name="unfold" />
</local:states>
<local:transitions>
<s:Transition toState="fold">
<s:Sequence>
<s:Resize target="{this}" duration="400" />
<s:RemoveAction target="{body}" />
</s:Sequence>
</s:Transition>
<s:Transition toState="unfold">
<s:Resize target="{this}" duration="400" />
</s:Transition>
</local:transitions>
<s:Group id="header" width="100%">
<s:Rect height="40" width="100%">
<s:fill>
<s:SolidColor color="0xff0000" />
</s:fill>
</s:Rect>
</s:Group>
<s:Group id="body" includeIn="unfold" y="40" width="100%">
<s:Rect height="200" width="100%">
<s:fill>
<s:SolidColor color="0x00ff00" />
</s:fill>
</s:Rect>
</s:Group>
</local:Base>
after all,i placed three of FoldUnit in main application to simulate an accordion component.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
<s:Group>
<s:layout>
<s:VerticalLayout variableRowHeight="true" />
</s:layout>
<local:FoldUnit />
<local:FoldUnit />
<local:FoldUnit />
</s:Group>
</s:Application>
everything like fine,however,if i try to click one red header to fold up,that green body just disappear immediately,looks like that RemoveAction tag is useless.
so,as i try to figure out why,i made things simple first,and i combine that function in Base.as into FoldUnit.mxml,then it works fine.
so,i wonder is there a bug or something?
PS:i don't wanna use a skinable component,coz' the size measure process always delayed,it's hard to location the scroll position in scroll bar.

flex prevent selection state on spark list

I have an ItemRenderer in which the selected state should be disabled (I'm using the renderer states and I don't have a selected state).
The problem is that the list (spark) resets the item renderer state upon click even though I don't have a "selected" state.
I want to fully prevent this behavior but I don't know how.
My renderer has autoDrawBackground set to false but it has to be enabled (although enabled=false fixes this issue)
Also, the renderer has several children including a list of its own.
Setting mouseEnabled="false" on the renderer fixes the renderer itself but not its children, and I need some of the children to be mouse enabled.
Edit:
Following is an excerpt from my item renderer:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
width="100%" autoDrawBackground="false">
<s:states>
<s:State name="normal" />
<s:State name="suitable" />
<s:State name="mine" />
<s:State name="deleted" />
</s:states>
<s:Rect id="rect" top="0" right="0" bottom="0" left="0">
<s:fill>
<s:SolidColor id="background"
alpha=".8" alpha.deleted=".4"
color="0xff0000" color.suitable="0x00ff00" color.mine="0x0000ff" />
</s:fill>
</s:Rect>
<s:Label id="name" left="4" top="4" right="40" />
<s:List id="myList" left="4" top="40" right="4"
contentBackgroundAlpha="0" borderVisible="false" horizontalScrollPolicy="off">
<s:layout>
<s:VerticalLayout gap="3" paddingBottom="4" requestedMinRowCount="2" />
</s:layout>
</s:List>
</s:ItemRenderer>
Second Edit:
I had the same problem with the mouse hover state but that seems to have a workaround:
override protected function set hovered(value:Boolean) : void
{
// do nothing (prevent current state from changing to "hovered" state)
}
I'm unclear if you want to prevent an item from being selected; or just prevent the visual properties that go along with an item being selected.
To handle the visual aspects; I'd try to override the getCurrentRendererState() method. Something like this:
override protected function getCurrentRendererState():String{
if (selected && hasState("selected"))){
return "normal"; // or whatever state you want it to be
}
if (selected && down && hasState("downAndSelected")){
return "normal"; // or whatever state you want it to be
}
super.getCurrentRendererState()
}
In theory, this should prevent your renderer from ever going into a selected state.

Is there a style that will change the caret selection color in a Spark List?

Is there a style or property that will change the caret selection color in a Spark List?
Note: The caret selection is the border color around a row when using the keyboard navigation. It is not the selected row.
Okay, tested around a bit and
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true" height="60">
<fx:Script>
<![CDATA[
[Bindable] public var color1:uint = 0xE54545;
[Bindable] public var color2:uint = 0xE5D145;
[Bindable] public var color3:uint = 0xA3E545;
[Bindable] public var color4:uint = 0x45E5C6;
[Bindable] public var color5:uint = 0x4564E5;
[Bindable] public var color6:uint = 0xE545C6;
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
<s:State name="selected"/>
<s:State name="normalAndShowsCaret"/>
<s:State name="hoveredAndShowsCaret"/>
<s:State name="selectedAndShowsCaret"/>
</s:states>
<s:Rect left="0" right="0" top="0" bottom="0">
<s:stroke.normalAndShowsCaret>
<s:SolidColorStroke
color="{color1}"
weight="1"/>
</s:stroke.normalAndShowsCaret>
<s:stroke.hoveredAndShowsCaret>
<s:SolidColorStroke
color="{color2}"
weight="1"/>
</s:stroke.hoveredAndShowsCaret>
<s:stroke.selectedAndShowsCaret>
<s:SolidColorStroke
color="{color3}"
weight="1"/>
</s:stroke.selectedAndShowsCaret>
<s:fill>
<s:SolidColor
color.normal="{color1}"
color.normalAndShowsCaret="{color2}"
color.hovered="{color3}"
color.hoveredAndShowsCaret="{color4}"
color.selected="{color5}"
color.selectedAndShowsCaret="{color6}"
/>
</s:fill>
</s:Rect>
<s:Label text="{data}"/>
</s:ItemRenderer>
and the actual caret color is third stroke, "s:stroke.selectedAndShowsCaret". Why my first comment didn't work was because it is also binded to color="{selectionColor}" by default, so you need to make a custom itemrender or adjust your current itemrenderer to match.
Yes, it's property "selectionColor"
list.setStyle("selectionColor", "#SOME_VALUE") or <s:List id="list" selectionColor="red"/>

Flex: Custom ProgressBar bar skin won't fill entire track

I'm trying to create a simple skin for the flex progressbar control. Both the track and the bar should have rounded corners, and the bar should fill the track completely in the parts where it is being shown.
Here is the bar skin I've created based off this example:
<?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:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
override protected function initializationComplete():void {
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<s:Rect radiusX="5" radiusY="5" top="0" left="0" right="0" bottom="0">
<s:fill>
<s:SolidColor color="#bb0203" />
</s:fill>
</s:Rect>
</s:SparkSkin>
Here is the progress bar declaration:
<mx:ProgressBar id="progressBar" name="progressBar" top="40" left="10" width="480" height="25"
label="" labelWidth="0"
trackSkin="Skins.ProgressBar.TrackSkin"
barSkin="Skins.ProgressBar.BarSkin" />
And here is the track skin:
<?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:mx="library://ns.adobe.com/flex/mx"
minHeight="25">
<fx:Script>
<![CDATA[
override protected function initializationComplete():void {
useChromeColor = true;
super.initializationComplete();
}
]]>
</fx:Script>
<s:Rect width="100%" height="100%" radiusX="5" radiusY="5">
<s:fill>
<s:SolidColor color="#d1d3d4" />
</s:fill>
</s:Rect>
</s:SparkSkin>
Unfortunately, it doesn't have quite the desired effect:
Instead of the bar being flush with the track, there's a margin, and the rounded border gets cut off.
How do I fix this?
In addition to setting the barSkin property, set the maskSkin property to the same value as barSkin:
You can assign this skin the same way as others in your code:
<mx:ProgressBar id="progressBar" name="progressBar" top="40" left="10" width="480" height="25"
label="" labelWidth="0"
trackSkin="Skins.ProgressBar.TrackSkin"
maskSkin="Skins.ProgressBar.BarSkin"
barSkin="Skins.ProgressBar.BarSkin" />

Flex 4: mx|tree - how can i disable items selection?

I want to create a tree that it's child nodes contain specific flex components that I created. I override the default ItemRenderer to achieve this.
In my ItemRenderer i have:
two states: item and root_item.
a function that executes after creation complete that using the data validates the proper state that this component should be in and changes the currentState to the desired state.
My problem is that once the user clicks on any of the elements, it changes automatically to the first state which mess things up.
how can I disable items selection at all ? of course I want the user to be able to drill up and down the trees but not to select the items.
thanks!
update
The Item changes states on hover effect, so or I disable items selection or somehow i prevent the hover effect from changing the state.
another update
this is my code:
the main TreeTest.xml:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" autoLayout="false" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<fx:XML id="treeData">
<node label="notifications">
<node label="Winnings" is_root="yes">
<node label="winner"/>
</node>
<node label="Challenges" is_root="yes">
</node>
<node label="Achievements" is_root="yes">
</node>
<node label="Lucky charms" is_root="yes">
</node>
<node label="Friend requests" is_root="yes">
</node>
</node>
</fx:XML>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.controls.listClasses.ListBase;
import mx.events.ListEvent;
protected function tree_itemClickHandler(event:ListEvent):void
{
tree.selectedItem = null;
event.preventDefault();
}
protected function tree_itemRollOverHandler(event:ListEvent):void {
event.preventDefault();
}
]]>
</fx:Script>
<mx:Tree id="tree" itemRollOver="tree_itemRollOverHandler(event)" itemClick="tree_itemClickHandler(event)" dataProvider="{treeData}" folderOpenIcon="{null}" folderClosedIcon="{null}" defaultLeafIcon="{null}" width="1024" height="768" labelField="#label" itemRenderer="TreeItemRenderer" showRoot="false" allowMultipleSelection="false" allowDragSelection="false"/>
</s:Application>
as you can see here I tried to prevent both itemRollover and itemClick but it did not resolve my problem.
this is the TreeItemRenderer.xml:
<?xml version="1.0" encoding="utf-8"?>
<s:MXTreeItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="init()">
<s:states>
<s:State name="root_item" />
<s:State name="item" />
</s:states>
<fx:Script>
<![CDATA[
import com.flexer.Debug;
import mx.binding.utils.ChangeWatcher;
import mx.controls.Alert;
import mx.events.StateChangeEvent;
private function _stateChangeEventHandler(e:StateChangeEvent):void {
Alert.show("state changed to " + e.target.currentState);
}
private function init():void {
var theXML:XMLList = XMLList(this.data);
var theState:String =( theXML.attribute("is_root") == "yes" ? "root_item" : "item");
this.currentState=theState;
this.addEventListener(StateChangeEvent.CURRENT_STATE_CHANGE,this._stateChangeEventHandler);
// Alert.show(theXML.attribute("is_root"));
// Alert.show(theXML.attribute("label") + (theXML.attribute("is_root") == "yes" ? "true" : "false"));
}
]]>
</fx:Script>
<s:HGroup left="0" right="0" top="0" bottom="0" verticalAlign="middle" includeIn="root_item">
<s:Rect id="indentationSpacer" width="{treeListData.indent}" percentHeight="100" alpha="0">
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Rect>
<s:Group id="disclosureGroup">
<s:BitmapImage source="{treeListData.disclosureIcon}" visible="{treeListData.hasChildren}" />
</s:Group>
<s:BitmapImage source="{treeListData.icon}" />
<s:Label id="labelField" text="{treeListData.label}" paddingTop="2"/>
</s:HGroup>
</s:MXTreeItemRenderer>
You can add an event handler to the tree for the itemClick event
itemClick="tree_itemClickHandler(event)"
Then in the event handler you can cancel the itemClick event
protected function tree_itemClickHandler(event:ListEvent):void
{
tree.selectedItem = null;
event.preventDefault();
}
Update:
The item renderer has 3 default states: normal, hovered, and selected. You need to use basedOn with the 3 default states to reference your custom states. Ideally you would want the state in your data so you can avoid all of the work you're doing in init(). It would also allow you to bind basedOn to the state of your data as such:
<s:states>
<s:State name="normal" basedOn="{data.#state}"/>
<s:State name="hovered" basedOn="{data.#state}"/>
<s:State name="selected" basedOn="{data.#state}"/>
<s:State name="root_item" />
<s:State name="item" />
</s:states>
Then regardless of the default state that is sent by the parent list the display will be based upon what is in your data.

Resources