Set Flex container layout padding with CSS - apache-flex

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>

Related

How to add an icon to an AdvancedDataGrid column header and keep word wrap feature for the text

As stated, I'm trying to obtain column headers consisting of an icon and wrappable text in a flex AdvancedDataGrid.
(EDIT: I forgot to mention an important part of the context: the columns are added dynamically, in actionscript. This apparently changes the behavior.)
I've tried using a custom mxml headerRenderer, like so:
<mx:headerRenderer>
<fx:Component>
<mx:HBox width="100%"
height="100%"
verticalAlign="middle">
<mx:Image source="<image_url>"
width="10%"
height="100%"/>
<mx:Text text="{data.headerText}"
width="90%"
height="100%"/>
</mx:HBox>
</fx:Component>
</mx:headerRenderer>
but for some reason, the text here is truncated instead of wrapped (it works outside of a renderer).
I've also tried creating a subclass of AdvancedDataGridHeaderRenderer and overriding createChildren to add the icon:
override protected function createChildren():void
{
var icon:Image = new Image();
icon.source = <image_url>;
icon.width = 16;
icon.height = 16;
addChild(icon);
super.createChildren();
}
but then, the icon and the text get superimposed.
I'm out of ideas on this. Anyone else?
It worked for me when I removed the height="100%" attribute from mx:Text in your headerRenderer.
UPDATE: it only works like this when I manually stretch the AdvancedDataGrid component. I'll look into how to make it work unconditionally.
When the height of the Text component was set to 100%, it was constrained to its parent HBox's height. Therefore when a word was wrapped and moved to the next line, it wasn't visible because the height of the Text component didn't allow for it to be visible.
If you remove this constraint, Text component's height will be determined dynamically based on its contents, as will headerRenderer's. Also add minHeight to your Text so that it is visible when it's loaded.
Here's the code (I also removed scrollbars because they were showing during resize):
<mx:headerRenderer>
<fx:Component>
<mx:HBox width="100%"
height="100%"
verticalAlign="middle"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Image source="<image_url>"
width="10%"
height="100%"/>
<mx:Text text="{data.headerText}"
width="90%"
minHeight="20"/>
</mx:HBox>
</fx:Component>
</mx:headerRenderer>
In case anyone is interested in how to do this with dynamically created columns, a combination of Hunternif's code for the renderer and some added code on column creation worked for me:
The columns need to have fixed widths and need to be invalidated to inform the AdvancedDataGrid that it needs to rerender:
var cols:Array = [];
for each (...) {
var column:AdvancedDataGridColumn = new AdvancedDataGridColumn();
...
// Fix the width of created columns
column.width = 150;
cols.push(column);
}
grid.columns = cols;
// Invalidate columns so that sizes are recalculated
grid.mx_internal::columnsInvalid = true;
// Take changes into account
grid.validateNow();

Flex Vgroup Absolute positioning of components

I have a Vgroup with some components aligned par with its layout properties(vertical). I need to add one more component at an absolute X,Y position, overriding the alignment. I tried includeinlayout=false, but the component turns invisible then. Is it possible in flex?
No, this is not possible. A VGroup will ignore properties such as X, and Y. IF the component is visible, then includeInLayout is also ignored.
You'll have to layout your extra component outside of the VGroup, or switch to a Group and layout everything absolutely.
It is not possible! But you always can get global coordinates of the needed DisplayObject and show some PopUps or other components near to this target.
MXML:
<s:VGroup x="50" y="50">
<s:Button width="250" height="250" id="b1"/>
<s:Button width="250" height="250" id="b2"/>
</s:VGroup>
<s:Button id="addon"/>
AS:
var rect:Rectangle = b2.getBounds(this);
addon.x = rect.x + rect.width - addon.width;
addon.y = rect.y;

How to have a cornerradius on Flex 4 TextInput component

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.

Flex 4 UIMovieClip Modify the Width of a Child DisplayObject

I have a collection of UIMovieClip components which reside in an s:HGroup tag. In ActionScript code I am modifying the width of a child clip in one of the UIMovieClips but these changes are not reflected by the s:HGroup.
<s:HGroup id="_buttonGroup">
<uiassets:NavigationTabButtonSWC id="_lobby" />
<uiassets:NavigationTabButtonSWC id="_achievements" />
</s:HGroup>
<fx:Script>
<![CDATA[
protected function init() : void
{
// The HGroup does not pickup this change and so my buttons
// are no longer evenly spaced out and overlap!
_lobby.getChildByName("background").width += 200;
}
]]>
</fx:Script>
Thanks!
There's a few reasons for this. Just changing one child's width doesn't mean it'll change the whole UIMovieClip's width, so you should check that first.
Second, Flex has a very specific way of doing things (called the component lifecycle), which the UIMovieClip doesn't implement so you can't manage the width yourself in the 'measure' function. I'm guessing that you just have other children in your movieclip that doesn't let you resize it all. Try changing the width of the MovieClip itself and it should work. If it doesn't, then there's another problem.

Setting the gap of layout

I usually set the layout like this
<s:Group>
<s:layout>
<s:VerticalLayout gap="10"/>
</s:layout>
</s:Group>
but not sure how to specify the gap if I want to use new VerticalLayout
The VerticalLayout constructor does not have any parameters, so you won't be able to do this in-line in MXML as part of the layout property. You'll have to set the gap property on the layout after creating it. Perhaps in a creationComplete handler, do something like this:
groupID.layout.gap = 10;
You can probably even do this in-line:
<s:Group layout="{new VerticalLayout()}" id="groupID" creationComplete="{groupID.layout.gap = 10}"></s:Group>

Resources