How can I animate between states in a programmatic skin? [FLEX] - apache-flex

I have a button with the various states (up/over/down etc) that uses a skin file to render the display. I want to achieve animation between the states. For instance, between the change from 'up' to 'over' I want to fade in a color and a border.
The way I am doing this at the moment is to use viewstates and animate between them using transitions and the mx:AnimateProperty. However, using this method I can only animate one property per viewstate. So only the border, or the color can be animated.
Does anyone know how I can achieve multiple animations on multiple properties of a programmatic button skin? Thanks in advance!
Note: I have looked into using tweener but cannot see how it would help my situation

http://www.degrafa.org/
http://www.degrafa.org/source/AdvancedSkins/Skins.html

Lewis,
You will not be able to animate any properties of a ProgammaticSkin in Flex 3 because the way UIComponent does skins is by instantiating an entire new instance of your skin and then setting its name property. Then when the component needs to display a new state, it makes another new instance, sets its name property to something different, makes the old skin invisible and makes the new skin visible. In this way, it "caches" the skins, instead of switching states and redrawing in UpdateDisplayList.
Now because of that you can't easily animate any drawing of the skin itself, however, there is a solution although it's not entirely elegant.
ProgammaticSkin extends FlexShape, so you can't add any children to your skin, but UIComponent looks for something that implements IProgrammaticSkin, so you can make your own ProgrammaticSkin that extends FlexSprite instead of FlexShape. This allows you addChild to your skin. If you are clever enough, you can synchronize transitions between the various cached skins to make them animatable.
Hope that helps,
Jonathan

Since you use skin files I suppose you use Flex4.
In Flex4, you can use multiple mx:AnimatePropery declarations wrapped in a s:Sequence or s:Parallel node.
<s:transitions>
<s:Transition>
<s:Parallel>
<mx:AnimateProperty
target="{button}"
property="property1"
fromValue="property1StartValue"
toValue="property1EndValue" />
<mx:AnimateProperty
target="{button}"
property="property2"
fromValue="property2StartValue"
toValue="property2EndValue" />
</s:Parallel>
</s:Transition>
</s:transitions>

Related

TitleWindowSkin, TitleWindowCloseButtonSkin, colorization: how do I duplicate this behavior in a custom component?

I am trying to use the spark.skins.spark.TitleWindowCloseButtonSkin in a custom component and make it look thematically similar to how it looks in TitleWindow. Just specifying it as the skin class for a Button works no problem. I also have a .css style applied to all my TitleWindow classes that affects the close buttons in a TitleWindow. If I set the chrome color of the TitleWindow in .css then the close button skin also gets colorized to match this color. My custom component is also using the same style reference as my TitleWindows. But the Button instance inside of my custom component does not get colorized. So while I have blue TitleWindows with blue-colorized closed buttons, I have a blue custom component with a default gray background closed button (on button-press, the gray background appears).
There must be something going on with TitleWindowSkin and TitleWindowCloseButtonSkin via the colorization mechanic but I don't understand what it is. How should I solve this problem? I need to make the close button style in my custom component match that of the close button in my TitleWindows.
Here is a picture of the problem:
The TitleWindow is on the left in both pictures. The custom component is on the right.
In the left frame, you see the TitleWindow close button in the down position, note that its down state is colorized to match the theme of the TitleWindowSkin. On the right you see the down state of the custom component's close button. I do not know how to colorize the default gray to match the blue theme applied to the custom component.
I am sure there are a multitude of ways to solve this. I am looking for the most "correct" way. I do not want to hard-code colors because later an actual designer will come in and tweak the .css.
PS My custom component extends from spark.components.Group. Could that be a problem???
I should also mention that normal Button instances that use the default spark ButtonSkin do seem to get styled properly in the custom component (part of the reason this problem is so frustrating).
EDIT: yes, yes indeed it looks like the first step to a solution is to inherit from SkinnableComponent not Group or UIComponent...
In your TitleWindowSkin you need to add "closeButton" in exclusions array at top, I have resolved the same issue with this.
hm, this is curious since I can't seem to find any reference to chrome color or anything within the close button skin:
<s:Rect left="0" top="0" right="0" bottom="0">
<s:stroke>
<s:SolidColorStroke color="0x000000"
alpha="0.0"
alpha.over="0.7"
alpha.down="0.7"
weight="1"/>
</s:stroke>
<s:fill>
<s:SolidColor color="0xCCCCCC" alpha="0" alpha.down="0.7" />
</s:fill>
</s:Rect>
If I were you, I'd just create a skin based on the close button skin and have a reference to a style color using getStyle which can be changed in the css.
Ok, so I have mostly figured out the problem. It stems from the fact that I am not using a proper skin technique on my custom component. The custom component logic is fine where it is at, but I need to prepare a separate skin class that actually instantiates the custom component's "parts" (ie: sub-components). Currently, the custom component does this in createChildren(). Furthermore, to take advantage of the colorization mechanic, the skin class must inherit from SparkSkin. The TitleWindowCloseButton instance needs to be a member of the custom component's skin class (as well as having a reference in the custom component class). SparkSkin will automatically color transform (colorize) every child of the custom component's skin unless it is explicitly excluded. Finally, back in the custom component, override partAdded() and when "closeButton" comes up, add the close button's event handler at that time. Feels very Cairngorm-ey... but I digress (must suppress urge to rant about the stoopid that are "helper" classes).

Adding functionalities to the right border of an AdvanceDataGrid component

I'd like to add some functionalities to the right border of my ADG component to help the user resize and potentially do more stuff. Is there a skin for that border? For instance, how would you make it wider, or add a handle that perhaps animates when you hover over it?
thank you, yet again!
There is no skin that allows you to do this. You have only two options:
Extend ADG and add the desired functionality.
Create a custom component that can contain an ADG and add additional components und functionality to your custom component.
Extending ADG is no fun at all. So, if possible I'd choose option 2. In MXML it could look something like this:
<ns1:MyAdvancedDataGridContainer>
<ns1:dataGrid>
<mx:AdvancedDataGrid ...>
<!-- your columns and stuff like that -->
</mx:AdvancedDataGrid>
</ns1:dataGrid>
</ns1>
MyAdvancedDataGridContainer would add all the fancy stuff you need without the need of changing and overriding lots of ADG's ugly code.

Animating a sequence of images in the background using Flex 3/Actionscript?

I would like to animate a sequence of background images within a uicomponent but also dynamically add and remove components to this component.
My first question would be:
1.) What's the best way to animate a sequence of images using Flex 3?
2.) What's the best way to handle adding and removing components on top of the background dynamically?
Any help/information would greatly be appreciated!
Thank you!
In the mxml for your ui component declare an mx:Image and give it an id. Set up a timer loop that changes the "source" attribute (id.source = ) on your mx:Image at an interval you like. To add and remove components dynamically just use addChild/removeChild or addElement/removeElement depending on the type of display object you're working with. The mx:Image should always be behind the dynamically added components as it was created and added before them.

Flex 4 ItemRenderer Question

I have a DataGroup with a Custom ItemRenderer. Within the itemrenderer, there are 2 states. normal and hovered. I have a <s:Group> within the itemrenderer that shows a bunch of data but i only want to be shown when hovered so I can do includeIn="hovered" which is good.
the problem is the x,y position of this group needs to be outside the bounds of the container itself. much like a tooltip only that this is not a tooltip.
whatever i do, it stays within the bounds of the datagroup. any ideas? or am I missing something simple here?
The behavior you are describing sounds an awful lot like a tooltip/datatip. Why not create your own tooltip skin and assign it to your renderer instead of re-inventing tooltips?
EDIT: Based on the comment below, the approach I would consider is to show a custom skinned Panel or ToolTip when entering the hovered state using the PopUpManager.addPopUp method. After adding it, then position it where ever you like. You'll probably need to change the local coordinates to the global coordinates when moving your popup. Then call PopUpManager.removePopUp when exiting the hovered state. Hope that helps.

What's the easiest way to create an extensible custom container in Flex?

I want to create an MXML container component that has some of its own chrome -- a standard query display, et al -- and that supports the addition of child components to it. Something a lot like the existing mx:Panel class, which includes a title label, but acts like a plain mx:Box with regards to adding children.
What's the easiest way to do this?
Edit:
To be clear, I want to be able to extend the container using MXML, so the "Multiple visual children" problem is relevant.
Extend a container and add a title label. Probably the <mx:Canvas/> will work here. Make the title a public var and include a var for the styleName of the label.
Then override the addChild() method so that any child that is added is added instead to the that is your container.
Leave enough space for your title when you position your Box element (i.e., give its y property enough space. If there is no title you may want to reclaim that space.
That's the basics. Customize to your heart's content.
EDITED TO ADD: I do this creating an ActionScript class first, extending the container I am targeting, and I add the "furniture" — items the class will always use, like title in your case — by overriding createChildren and calling super.addChild(item) for those items. Calling addChild from then on, even in MXML markup, adds items to the inner container.
We do this with states.
We put the chrome for the base container in a state (in mx:AddChild elements) and then use the initialize event to switch to that state when the control is created. All the chrome is then added to the container.
That gets round the multiple sets of visual children problem.
The downsides to this approach are:
You don't see the chrome when editing descendents of the base.
You can't directly access the parent chrome controls from descendent components as they are not there at compile time (instead, you need to define properties, methods or events on the base that the descendents can access)
However, it works well for us.

Resources