Flex 4 Panel Border Skin - apache-flex

I'm trying to create a skin for a Flex 4 spark Panel that will create a border on the left/right side of the panel that matches the header of the Panel. Basically a silver frame all the way around the edge of the Panel similar to the old Flex 3 mx:Panel. I've been experimenting with a skin file all day and can't get anything to work. Any ideas?

I threw something together real fast. Create a Skin based on the existing PanelSkin. Then go find the group with id="contentGroup". Change it to something like this:
<s:Group width="100%" height="100%" minWidth="0" minHeight="0">
<s:Line stroke="{wrapperStroke}" top="0" left="0" bottom="{0}" yFrom="0" yTo="{this.height}" xFrom="0" xTo="0"/>
<s:Line stroke="{wrapperStroke}" top="0" right="0" bottom="{0}" yFrom="0" yTo="{this.height}" xFrom="0" xTo="0"/>
<s:Group id="contentGroup">
</s:Group>
</s:Group>
Then all you need to do is move your contentGroup away from the edges and give the stroke a color and weight. So, head to the updateDisplayList in the skin and add some code like:
wrapperStroke.color = 0xD9D9D9;
wrapperStroke.alpha = 1.0;
wrapperStroke.caps = CapsStyle.SQUARE;
wrapperStroke.weight = 3;
contentGroup.top = 3;
contentGroup.bottom = 3;
contentGroup.left = 3;
contentGroup.right = 3;
Also just put your wrapperStroke in a Declarations area like so:
<fx:Declarations>
<s:SolidColorStroke id="wrapperStroke" />
</fx:Declarations>
I hardcoded everything but you should be able to easily get them as Styles. Your PanelSkin should now look like this. I increased the weight of the stroke so it's easier to see.

Related

flex how to set the tilegroup scroller still keep on the bottom

My component code is hereļ¼š
<s:BorderContainer id="bcMySeriesParameters" top="100" bottom="45" width="1030"
borderVisible="false" horizontalCenter="0">
<s:Scroller id="scrollerForTgpMySeriesParameters" left="5" height="100%" width="1020">
<s:TileGroup id="tgpMySeriesParameters" left="0" top="0" width="1020"
horizontalAlign="center" horizontalGap="5" requestedColumnCount="5"
verticalAlign="top" verticalGap="5">
</s:TileGroup>
</s:Scroller>
</s:BorderContainer>
And I have another button which loads more parameters and adds these parameters to the tgpMySeriesParameters. I want to achieve when loading more parameters, the scrollerForTgpMySeriesParameters still keeps on the bottom, like this
You can adjust the scroller position by using Scroller.viewport.verticalScrollPosition.
In your function that appends more data to your TileGroup:
scrollerForTgpMySeriesParameters.viewport.verticalScrollPosition = int.MAX_VALUE;
For a more advanced scenario (say your scrollbar is halfway down, and you want to keep it at the halfway point out of all the items in the group rather than keep it at the same number of items from the top), you could check the value of verticalScrollPosition and then add to it:
var numAdded:int = listOfParametersToAddToTheTileGroup.length;
var currentPos:int = scrollerForTgpMySeriesParameters.viewport.verticalScrollPosition;
//add more parameters to your tgpMySeriesParameters
currentPos += numAdded * tileHeight;
scrollerForTgpMySeriesParameters.viewport.verticalScrollPosition = currentPos;

Spark List - alternatingItemColors - extend to bottom

In the good old mx world, the alternatingItemColors extend all the way to the height of the list. In the spark list, it stops where the data ends. Does anyone know if there is an easy way to make the Spark list behave similar to the mx list? See the image below. there is white space below the list, this does not happen in the mx list.
The difficulty will depend on how flexible your solution must be, but in general I think your best bet would be to create a custom skin for this List.
Create a custom skin
You can start by copying the Spark List skin (spark.skins.spark.ListSkin) and making some minor modifications to it:
<!-- AlternatingColorListSkin.mxml -->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("spark.components.List")]
</fx:Metadata>
<s:states>
<s:State name="normal"/>
<s:State name="disabled"/>
</s:states>
<s:Rect id="background" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:SolidColor id="bgFill" color="0xEEEEEE"/>
</s:fill>
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1"/>
</s:stroke>
</s:Rect>
<s:Group id="oddRowGroup" left="1" right="1" top="1" bottom="1" clipAndEnableScrolling="true"/>
<s:Scroller id="scroller" left="0" top="0" right="0" bottom="0" minViewportInset="1" hasFocusableChildren="false">
<s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer">
<s:layout>
<s:VerticalLayout id="dataLayout" gap="0" horizontalAlign="contentJustify" requestedMinRowCount="5"/>
</s:layout>
</s:DataGroup>
</s:Scroller>
</s:Skin>
In the code above I left out the portions of ListSkin that are irrelevant to this answer and I made these modifications:
the background fill color is the color of the even rows (instead of white by default)
I added 'oddRowGroup' to which we'll be adding some darker rectangles
I gave the DataGroup's layout an id (dataLayout) so that we can easily access it later
Add the odd row backgrounds
We'll now be adding the odd row backgrounds to oddRowGroup dynamically. Note that oddRowGroup's left/right/top/bottom is 1 so that the row backgrounds will not overlap the main background's border. It also has clipAndEnableScrolling set to true which will cause any possible overlap of the last odd row to be clipped.
Now add the following code in a script block in the skin:
private var previousHeight:Number = NaN;
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (previousHeight != unscaledHeight) refreshBackground(unscaledHeight);
previousHeight = unscaledHeight;
}
private function refreshBackground(height:Number):void {
var rowHeight:Number = dataLayout.rowHeight;
var maxRows:int = height / rowHeight / 2;
oddRowGroup.removeAllElements();
for (var i:int = 0; i < maxRows; i++) {
var row:FilledElement = new Rect();
row.left = row.right = 0;
row.height = rowHeight;
row.top = (i * 2 + 1) * rowHeight;
row.fill = new SolidColor(0xdfdfdf);
oddRowGroup.addElement(row);
}
}
What happens here?
In updateDisplayList (which is called amongst others each time the List is resized), we check whether the height has changed. If it has, we refresh the odd row backgrounds.
We do so by removing all backgrounds that were drawn for the previous height.
We get the rowHeight from the DataGroup's layout, and we calculate the total number of required backgrounds. Then we create some Rects based on these numbers and we add them to oddRowGroup.
Limitations
The solution as it is, has some limitations. For instance the alternating colors are hardcoded (which can easily fixed by getting the right colors using getStyle()); it assumes there will be no override of the default layout (which is a VerticalLayout); it assumes variableRowHeight is off; and probably some more. But I think it's a good starting point.

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.

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