How to have a cornerradius on Flex 4 TextInput component - apache-flex

How do I get corner radius on my TextInput component in Flex 4.
<s:TextInput prompt="username" width="150" maxChars="100" id="txt_username"
color="#000000"/>

Create a custom skin (possibly by copying spark TextInputSkin) and add a border graphic with rounded corners, like this:
<!-- border -->
<s:Rect id="border" left="0" right="0" top="0" bottom="0"
radiusX="10" radiusY="10">
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1" />
</s:stroke>
</s:Rect>
If you want more special rounded corners you can also use these attributes:
topLeftRadiusX="4" topLeftRadiusY="8"
bottomLeftRadiusX="2" bottomRightRadiusY="10"
The default TextInputSkin does not allow for rounded corners, so there is no style that you could set on your TextInput to do it. So, no, there's no other way than creating a custom skin class.

You could take it a step further and make it dynamic. Create a custom TextInputSkin based on spark TextInputSkin and in the updateDisplayList method add this code above the super.updateDisplayList() call.
In YourTextInputSkin.mxml,
// in updateDisplayList()
if (getStyle("cornerRadius")!==undefined) {
border.radiusX = border.radiusY = getStyle("cornerRadius");
background.radiusX = background.radiusY = getStyle("cornerRadius");
}
That's it. You're done!
Now to use it add a CSS class selector to add a cornerRadius style like so:
/* set the Textinput.styleName to this style */
s|TextInput.roundedInput
{
contentBackgroundAlpha: .4;
contentBackgroundColor: #000000;
cornerRadius: 10;
skinClass: ClassReference("view.skins.TextInputRoundedSkin");
}
And set your instance to the class,
<s:TextInput styleName="roundedInput"/>
Unfortunately, you can't set the cornerRadius style on TextInput component instance in MXML. Should Flex support a styles tag for this type of thing like HTML tags do? Should styles declared in the Skin be proxied to the component using them? Currently the Flex compiler would throw an error if you declared a style in the Skin and tried to use it on the component instance even though it's valid to declare that style and any other style in the CSS. What about if UIComponents had a style proxy object that let you set styles? Anyway, I digress.
If you want to make that style available on the TextInput instance in addition to the previous methods you can do that by extending TextInput and adding the cornerRadius style metadata to it. You can also set the skinClass (inline or in a defaults.css file in the library) while you're at it.
Something like this:
<?xml version="1.0" encoding="utf-8"?>
<s:TextInput 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="TextInputRoundedSkin" >
<fx:Metadata>
[Style(name="cornerRadius", inherit="no", type="uint")]
</fx:Metadata>
</s:TextInput>
To use,
<local:MyExtendedTextInput cornderRadius="8" />
In the future you won't have to declare the CSS.

Related

Creating a new skin class for a ToggleButton

I'm using the following Flex component: http://flashcommander.org/blog/flex-4-mp3-player
The skin that comes with this component only allows for very basic skinning, such as background colour and borders. However the component makes use of a ToggleButton, defined in Mp3Player.as:
import spark.components.ToggleButton;
[SkinPart]
public var playPauseButton:ToggleButton;
What I would like to do is define an alternative skin for this control in the project, I'm pretty new to Flex and Spark so I'm un-sure as to how I go about define a new skin.
In the Mp3PlayerSkin.mxml file the skin is defined as follows:
<!--- #copy spark.components.VideoPlayer#playPauseButton -->
<s:ToggleButton id="playPauseButton" left="0" bottom="0"
skinClass="spark.skins.spark.mediaClasses.normal.PlayPauseButtonSkin"
focusIn="event.target.depth=1" focusOut="event.target.depth=0" />
I assume I can create a new class, although I don't know how to do that, or remove the reference to the class and extend the ToggleButton skin in some way. I'm thinking I need to override the 'default' skin in some way?
Any pointers appreciated ...
Looks like I can do the following:
Create a new Flex Skin by right-clicking the original Mp3PlayerSkin.mxml file
Name the file toggleButtonSkin.mxml
Copy the styles from the spark.components.VideoPlayer#playPauseButton class
Update the Mp3PlayerSkin.mxml as follows:
<s:ToggleButton id="playPauseButton" left="0" bottom="0"
skinClass="org.flashcommander.components.toggleButtonSkin"
focusIn="event.target.depth=1" focusOut="event.target.depth=0" />
Now I can edit the new toggleButtonSkin.mxml file by editing the new styles.

Set Flex container layout padding with CSS

Is there any way to use Flex CSS to set the padding on this BorderContainer?
<s:BorderContainer width="100%" height="100%">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Label text="asdfasdf" />
</s:BorderContainer>
I'm trying to avoid adding an extra unnecessary VGroup. Setting the padding with CSS has no effect. (I'm guessing since paddingLeft isn't a defined style on BorderContainer.)
s|BorderContainer {
paddingLeft: 10;
}
Is there any way to modify properties of the layout with CSS? I don't want to have to hard code padding in a ton of places.
You can add a custom style to the skin of your BorderContainer. Something like this:
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
var paddingLeft:* = getStyle('paddingLeft');
elementToPad.left = paddingLeft;
//or
layoutToPad.paddingLeft = paddingLeft;
//or
elementToPad.setStyle('paddingLeft', paddingLeft);
//depending on what kind of element you wish to pad
}
That way you can have different paddings applied through CSS, using a single Skin class and you can avoid code duplication.
Only downside is: you won't get IDE support because the host component won't know about the style you added; and the compiler will throw an error if you try to set the style in MXML, but that's what you were trying to avoid in the first place.
Define a custom syle whcih specifies the paddings.
.myCustomStyle { paddingLeft: 10;}
In the code, get this style value using styleManager and set it for the vertical layout
<s:layout>
<s:VerticalLayout paddingLeft= "value got from the style manager"/>
</s:layout>

How to understand the "id" attribute of flex skin?

I'm reading some source of flex skin, and found there are some id attributes, which seems important. Take a "button" skin for example:
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
minWidth="21" minHeight="21"
alpha.disabled="0.5">
<!-- host component -->
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<!-- layer 8: text -->
<s:Group id="textGroup" verticalCenter="1" left="25">
<s:filters>
<s:DropShadowFilter alpha="0.5" blurX="0" blurY="0" distance="1" />
</s:filters>
<s:Label id="labelDisplay"
textAlign="center"
verticalAlign="middle"
maxDisplayedLines="1">
</s:Label>
</s:Group>
</s:SparkSkin>
You can see there are ids of textGroup and labelDisplay. They are important since if I use other ids, the styles won't be applied to button.
But how don I know what ids should I use? Why it's textGroup and labelDisplay? Where can I find the declarations?
I tried to search them in the source of spark.components.Button.as, but not found anything related.
The IDs textGroup and labelDisplay are part of the skinning contract.
If you check the source for ButtonBase the class extended by the Button class you will notice:
[SkinPart(required="false")]
/**
* A skin part that defines the label of the button.
*
* #langversion 3.0
* #playerversion Flash 10
* #playerversion AIR 1.5
* #productversion Flex 4
*/
public var labelDisplay:TextBase;
Here as you can see the declaration tells you that labelDisplay is a TextBase in the skin and that the labelDisplay skin part is technically not required (required="false"), but without it, Flex would not draw a label on the Button control. The default value for the required property is false. The contract between the Button class and its skin dictates that when you set the label property on a button, the value is pushed down into the skin and modifies the value of the labelDisplay skin part’s text, if the labelDisplay skin part exists.
So essentially this means that these IDs will be used in the ButtonBase class. Usually no need to change the Ids unless of course your requirement needs you to do so. In which case you need to change the skinning contract appropriately too.
Check http://help.adobe.com/en_US/flex/using/WSC8DB0C28-F7A6-48ff-9899-7957415A0A49.html
section Skinning contract.
id is used to bind skin part instance in skin and logic in host component.

How can I add multiple icons to the Spark TabBar control?

In the MX TabBar component, the iconField property allowed us to display different icons in each tab. In Spark, there does not seem to be an inherent way to add icons to the TabBar. Does anyone have an example of implementing icon support for Spark's TabBar? Is there a way to do this without extending the component?
Many thanks!
Hey after spending a week trying to follow multiple ways, (yours being top of the list) i found out a simpler and effective way to add icons to my tab bar, or any other component using skinning.
You dont need to create a custom component, just passing the icon and label through data.
http://cookbooks.adobe.com/post_Tutorials_for_skinning_Spark_ButtonBar_component_w-16722.html
As personally, i was using content navigator with my tabbar/viewstack, i passed the icon as icon instead of imageicon. you can make changes accordingly.
You'll have to create a skin for adding icons to Spark components; it is not as straightforward (IMHO) as Flex 3's MX components, though much more extensible.
Here are a few links which might help you get started:
Tour de Flex Tabbar examples
Custom Skin on Tabbar
Flex Tabbar with Skin
I believe I've come up with a solution, which I'm posting below for posterity. If anyone has a better way, I'd much appreciate the suggestion.
<!-- main app: TabBar implementation -->
<s:TabBar
dataProvider="{contentTabBarPrimaryDP}"
skinClass="skins.ContentTabBarSkin"/>
<!-- skins.ContentTabBarSkin: ItemRenderer implementation -->
<s:DataGroup id="dataGroup" width="100%" height="100%">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<custom:IconButtonBarButton
label="{data.label}"
icon="{data.icon}"
skinClass="skins.ContentTabBarButtonSkin"/>
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
<!-- skins.ContentTabBarButtonSkin: icon implementation -->
<s:HGroup
gap="3"
paddingBottom="3"
paddingLeft="3"
paddingRight="3"
paddingTop="3"
verticalAlign="middle">
<!--- layer 2: icon -->
<s:BitmapImage id="iconDisplay"
left="5"
verticalCenter="0" />
<!--- layer 3: label -->
<s:Label id="labelDisplay"
textAlign="center"
verticalAlign="middle"
maxDisplayedLines="1"
horizontalCenter="0" verticalCenter="1"
left="10"
right="10"
top="2"
bottom="2">
</s:Label>
</s:HGroup>
This solution uses a custom DTO object for the TabBar dataProvider which stores the label text as well as the embedded icon image as a class. I also had to extend the ButtonBarButton component to add an iconDisplay SkinPart, which looks like this:
[SkinPart(required="false")]
public var iconDisplay:BitmapImage;
This class also has getters/setters for the icon class property and sets the icon source, as such:
public function set icon(value:Class):void {
_icon = value;
if (iconDisplay != null)
iconDisplay.source = _icon;
}
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
if (icon !== null && instance == iconDisplay)
iconDisplay.source = icon;
}
It's seems to be a bug/missed functionality of the your SDK version:
http://forums.adobe.com/thread/552543
http://bugs.adobe.com/jira/browse/SDK-24331
Anyway, thanks for the solution with skins - very helpful

How to create a vertical gradient in flex

How to create vertical gradient in flex.
What i currently have is a horizontal color gradient. And its working fine. But I am unable to figure out how should I make it vertical (which ofcourse is the requirement)
I use styleName = "chatWindowLeftGradient"
<mx:VBox id="chatTabBarVBox" height="100%" styleName="chatWindowLeftGradient">
</mx:VBox>
And the style sheet looks like this:
<mx:Style>
.chatWindowLeftGradient{
backgroundImage: ClassReference("custom.GradientBackground");
backgroundSize: "100%";
fillColors: #6db263, #a4d9a1;
fillAlphas: 1, 1;
}
</mx:Style>
This give a gradient from top to bottom. How i can make from left to right??
Regards
Zeeshan
This won't just plug into your css, but a vertical gradient in Flex 4 mxml looks like this:
<s:Rect right="0" top="0" width="170" bottom="0">
<s:fill>
<mx:LinearGradient rotation="90">
<mx:entries>
<mx:GradientEntry color="#64574A"/>
<mx:GradientEntry color="#FFFFCC"/>
</mx:entries>
</mx:LinearGradient>
</s:fill>
</s:Rect>
Have you tried adding a rotation="90" to your style?
In Flex 3, the easiest way to apply a gradient to an element is to use Degrafa and its excellent CSSSkin class. Some good examples of its flexibility are here: Nice and Easy Gradients with CSSSkin
You can do it with a programmatic skin.
Create a new class that inherits from Border.
Override updateDisplayList with something like this:
super.updateDisplayList(w,h);
var g:Graphics = this.graphics;
g.clear();
var m:Matrix = new Matrix();
m.createGradientBox(w,h);
g.lineStyle(0,0,0);
g.beginGradientFill(GradientType.LINEAR,[color1,color2], [alpha1,alpha2], [0,0xFF],m);
g.drawRect(0,0,w,h);
g.endFill();
Reference this class as your skin using the ClassReference in the style section.

Resources