Moving spark.components.Application's ControlBar to its bottom - apache-flex

How can Application's ControlBar be moved to its bottom in Flex 4.5 ?
The Adobe doc says only:
By default, the ApplicationSkin class defines the control bar area to
appear at the top of the content area of the Application container
with a grey background. Create a custom skin to change the default
appearance of the control bar.
So I look at spark.skins.spark.ApplicationSkin and there is a controlBarGroup (does it hold the ControlBar contents?), but I don't know how to move it from top to the bottom.

First thing you have to do is create a custom skin class. In FlashBuilder (FB) there's an option to create one automatically, but in essence it's just a class like any other.
In FB, right-click somewhere in your project and select 'New > MXML Skin'
Then fill in the wizard form as follows:
Otherwise just create a new .mxml file and copy/paste the code from spark.skins.spark.ApplicationSkin into it.
Then in your application assign the skin class you've just created:
<s:Application ... skinClass="skins.MyApplicationSkin" />
Now let's edit your newly created skin class. This is the part that is of interest to you (I'll cut out some pieces to make it clearer):
<s:Group left="0" right="0" top="0" bottom="0">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<s:Group id="topGroup" minWidth="0" minHeight="0"
includeIn="normalWithControlBar, disabledWithControlBar" >
<!-- some graphic elements here -->
<s:Group id="controlBarGroup" left="0" right="0" top="1" bottom="1" ...>
<s:layout>
<s:HorizontalLayout ... />
</s:layout>
</s:Group>
</s:Group>
<s:Group id="contentGroup" width="100%" height="100%" ... />
</s:Group>
Almost there. Now all we need to do, is move that 'topGroup' beneath the 'contentGroup'. 'topGroup' contains some graphics + the controlBarGroup. 'contentGroup' is the area where all components will be inserted that you but in you application .mxml file.
<s:Group left="0" right="0" top="0" bottom="0">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<s:Group id="contentGroup" width="100%" height="100%" ... />
<s:Group id="topGroup" minWidth="0" minHeight="0"
includeIn="normalWithControlBar, disabledWithControlBar" >
<!-- some graphic elements here -->
<s:Group id="controlBarGroup" left="0" right="0" top="1" bottom="1" ...>
<s:layout>
<s:HorizontalLayout ... />
</s:layout>
</s:Group>
</s:Group>
</s:Group>

You could try moving the control bar group under the content group and it should behave as expected, especially if you look at the parent group's layout(vertical).
If you would like to exercise even more control over it, override the partAdded method.

Related

bottom to top TileLayout

I need a TileLayout rendering elements bottom to top and right to left. Something like this:
I managed to trick the TileLayout for the "right to left" part, by setting the 'layoutDirection' attribute of my container to "rtl", but there is no equivalence for the vertical rendering.
<s:Group layoutDirection="rtl">
<s:layout>
<s:TileLayout columnWidth="250" horizontalGap="8"/>
</s:layout>
<!-- etc -->
<s:Group id="fakeGroup3" layoutDirection="ltr"/>
<s:Group id="fakeGroup2" layoutDirection="ltr"/>
<s:Group id="fakeGroup1" layoutDirection="ltr"/>
</s:Group>
Is there a simple way to achieve this? Or should I override TileLayout?!?
You can anchor your Tile layout group to the bottom of the page:
<s:Group width="100%" height="100%" id="outermostLayoutContainer">
<s:Group layoutDirection="rtl" width="100%" bottom="0">
<s:layout>
<s:TileLayout columnWidth="250" horizontalGap="8"/>
</s:layout>
<!-- etc -->
<s:Group id="fakeGroup3" layoutDirection="ltr"/>
<s:Group id="fakeGroup2" layoutDirection="ltr"/>
<s:Group id="fakeGroup1" layoutDirection="ltr"/>
</s:Group>
</s:Group>
The inner Group with bottom="0" will push up towards the top of the screen based on its children.

Custom drop down on mouse over

I'm making a custom component that shows a little drop down area after you hover on the username. I'm using two states, up and hover to toggle my drop down box.
My problem is that it thinks I'm leaving the component level Group after I leave the username. Then the second level group (my drop down) disappears.
I've tried re-attaching an event handler to my component level Group on a callLater in my mouse over function but that didn't work.
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
mouseOver="groupLogIn_mouseOverHandler(event)"
mouseOut="groupLogIn_mouseOutHandler(event)"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import spark.skins.SparkSkin;
protected function groupLogIn_mouseOverHandler(event:MouseEvent):void
{
this.currentState = "hover";
}
protected function groupLogIn_mouseOutHandler(event:MouseEvent):void
{
this.currentState = "up"
}
]]>
</fx:Script>
<s:states>
<s:State name="up"/>
<s:State name="hover"/>
</s:states>
<s:Label id="lblUsername" color="0xffffff" fontSize="14" right="18" top="5"/>
<s:Group includeIn="hover" width="160" height="110" top="20" right="0" >
<s:Rect top="0" right="0" bottom="0" left="0">
<s:fill>
<s:SolidColor color="0x1a1a1a"/>
</s:fill>
</s:Rect>
</s:Group>
</s:Group>
You need a "hitzone" for your mouse events. Right now parts of your component are completely transparent. When the mouse goes over a transparent zone, the MOUSE_OUT event is triggered. (When I say 'transparent', µi actually mean there's nothing there at all).
Luckily this can easily be fixed: just add a Rect that covers the entire area below the other components and set its alpha to 0. This makes the Rect invisible to the user, but it can still react to mouse events.
<s:Rect id="hitzone" top="0" right="0" bottom="0" left="0">
<s:fill>
<s:SolidColor alpha="0" />
</s:fill>
</s:Rect>
<s:Label id="lblUsername" />
...

Custom Drag and Drop Component: When i add a skin, drag and drop no longer works?

I have a skinnableContainer that acts as a container for other drag and droppable items. This container's drop functionality is added from it's parent at the same moment the container is added.
This all works fine until I add a skin class to the skinnableContainer, now none of the draggable items can drop into the container as it did before.
I assume that the Group component wrapping the content from within the skin is acting as a block somehow, but I'm not sure how to allow the drop functionality through it?
Any ideas?
EDIT skin code below:
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark" alpha.disabled="0.5">
<fx:Metadata>
[HostComponent("spark.components.SkinnableContainer")]
</fx:Metadata>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<!-- layer 1: border -->
<s:Rect left="0" right="0" top="0" bottom="0" radiusX="5" radiusY="5">
<s:stroke>
<s:SolidColorStroke color="0" alpha="0.50" weight="1" />
</s:stroke>
</s:Rect>
<s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" >
<s:layout>
<s:VerticalLayout/>
</s:layout>
</s:Group>
</s:Skin>
Your custom skin has no background fill, hence it's completely transparent except for the border. Because of this there is no "hitzone" to drop your items on (right now you will probably be able to drop them if you target exactly that 1px border).
The solution - obviously - is to give it a fill. No worries, if you want it to look transparent, just set its alpha to 0.
<s:Rect left="0" right="0" top="0" bottom="0" radiusX="5" radiusY="5">
<s:fill>
<s:SolidColor alpha="0" />
</s:fill>
<s:stroke>
<s:SolidColorStroke alpha="0.50" />
</s:stroke>
</s:Rect>

Problem with depth between two components in flex

I know what i am about to ask may be all too simple but i have been unable to find a solution to my problem.
I am developing an AIR app. I have a custom skin for windowedapplication of spark components. In that skin i have added a bitmapimage to set a background for the windowedapplication.
Also, i have a custom component called 'header', what it does is draw a few table headers.
Now, if i add header as <ui:header width="100%" and height="40"\>in the skins right after the bitmapimage then the header shows up as it is supposed to. But, if i put the header within the windowedapplication then it displays underneath the bitmapimage, which cant be seen unless the bitmapimage is removed.
I tried to fix this problem by changing the depth of the bitmapimage and the header component accordingly in order to make them appear in the right order but, this is not working for me.
If you have an idea, please help me out.
Thanks
Here are bits of the code
`
<s:WindowedApplication 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="ui.uiskin"
height = "728" width="910"
xmlns:ui="ui.*">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<ui:header x="0" y="{.0258*height}" depth="0"
height="{0.0774*height}" width="100%"/>
</s:WindowedApplication>
`
uiskin is
`
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:ui="com.youspin.components.ui.*"
depth="-10">
<!-- host component -->
<fx:Metadata>
[HostComponent("spark.components.WindowedApplication")]
</fx:Metadata>
<fx:Script>
<![CDATA[
]]>
</fx:Script>
<!-- states -->
<s:states>
<s:State name="disabledAndInactive" />
<s:State name="normalAndInactive" />
<s:State name="disabled" />
<s:State name="normal" />
</s:states>
<s:BitmapImage source="#Embed('../../images/ui/background.png')" depth="-10"/>
<s:TitleBar left="0" right="0" top="1"
height="{0.0258*height}"
skinClass="titleSkin"/>
<ui:header x="0" y="{.0258*height}" depth="0"
height="{0.0774*height}" width="100%"/>
</s:Skin>
`
and header is
`
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Rect width="100%" height="{.04*height}">
<s:fill>
<s:SolidColor color="black"/>
</s:fill>
</s:Rect>
<s:Rect width="100%" height="100%"
left="0" top="2"
alpha=".2"
>
<s:fill>
<s:SolidColor color="black"/>
</s:fill>
</s:Rect>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%"
top="2" left="0"
id="headingsGroup"
>
<mx:Image source="#Embed('../../images/header/logo.png')"
width="{0.2*headingsGroup.width}"
left="{0.015*headingsGroup.width}" top="{0.04*headingsGroup.height}"/>
<!-- left line drop -->
<s:Rect left="{.25*headingsGroup.width}" top="0"
width="2" height="{.23*headingsGroup.height}">
<s:fill>
<s:SolidColor color="black"/>
</s:fill>
</s:Rect>
<!-- middle line drop -->
<s:Rect left="{.50*headingsGroup.width}" top="0"
width="2" height="{.23*headingsGroup.height}">
<s:fill>
<s:SolidColor color="black"/>
</s:fill>
</s:Rect>
<!-- side line drop -->
<s:Rect left="{.75*headingsGroup.width}" top="0"
width="2" height="{.23*headingsGroup.height}">
<s:fill>
<s:SolidColor color="black"/>
</s:fill>
</s:Rect>
<s:Label text="artist"
top="{0.06*headingsGroup.height}"
horizontalCenter="{-0.125*headingsGroup.width}"
styleName="balonez"/>
<s:Label text="song"
top="{0.06*headingsGroup.height}"
horizontalCenter="{0.125*headingsGroup.width}"
styleName="balonez"/>
<s:Label text="album"
top="{0.06*headingsGroup.height}"
horizontalCenter="{0.375*headingsGroup.width}"
styleName="balonez"/>
<!-- bottom line -->
<s:Rect left="{.25*headingsGroup.width}" top="{.22*headingsGroup.height}"
width="{.75*headingsGroup.width}" height="2">
<s:fill>
<s:SolidColor color="black"/>
</s:fill>
</s:Rect>
</s:Group>
<fx:Style>
#font-face {
src:url("../../fonts/balonez fantasia.ttf");
fontFamily: myFontFamily;
advancedAntiAliasing:true;
}
.balonez{
font-family:myFontFamily;
font-size:25;
}
</fx:Style>
</s:Group>
`
Some parts of the code are not shown here, but i guess the above should give you an idea of what i am trying to do.
What i was trying to do is that my windowedapplication has a custom skin i.e, uiskin. And also there is a separate component called 'header'. Within uiskin.mxml i have added a bitmapimage to use it as the windowedapplication's background. And within the windowedapplication i have added the header. Doing this causes the header to appear behind the image.
For now, what i have done is added the header inside the uiskin after the bitmapimage. Now, this makes the header appear above the bitmapimage. But, i actually want to place the header within the windowedapplication and not within the custom skin. Is there a way to do this.
Can you show us some code ? Because when you add components to the display list using MXML, the order you write them in is important. For instance, the following code will add the label, and then the image. If the two components' coordinates overlap, the image will cover the label. The mxml part of a flex component is ran over from the top to the bottom. See ?
<s:Label
id="labelContent"
width="100%" height="100%"/>
<s:Image id="imageContent" horizontalCenter="0" verticalCenter="0"/>
I found the answer to my question. All that was needed was a group tag to make the content of the windowed application display above the image set in the windowedapplication skin
<s:Group id="contentGroup" left="0" top="0" right="0" bottom="0" />
Take care to keep the id as well, it didn't work for me when i removed the id. Also, here is the link if anyone needs it.
I Understand some of the things posted by you. If u place the Image and then header, the header hides the image. my solution is this
have a Hgroup with 100% 100% height width
<s:HGroup width="100%" height="100%">
<ui:header width="100%" height="40"\>
<s:Image width="100%" height="60%"\>
</s:HGroup>

Flex - How to change open DropDownList height

Using FB4, I want to change the height of an open spark DropDownList. By default, it shows up to 6 items before scrolling. My dropdownlist contains 7 items, so I want to change the height of the open dropdown list to fit all 7 items without scrolling. As a workaround, I've changed the font size of the items so that they are smaller and all 7 fit, but the smaller font doesn't look good. Is there a way to change this height? I'm rather new to Flash, so if it's a complicated solution, please be detailed :-).
Isn't it easier if you use the property requestedRowCount of the verticalLayout?
<s:DropDownList dataProvider="{myDataProvider}">
<s:layout>
<s:VerticalLayout requestedRowCount="10"/>
</s:layout>
</s:DropDownList>
The issue is, in Flex 4, the DropDownListSkin has defined maxHeight="134" for the default skin you are probably using. That forces the scrollbar to appear if the objects stretch beyond that height. All you need to do is copy/paste their DropDownListSkin code into a custom skin, and apply that to your DropDownList via CSS:
VariableHeightDropDownListSkin
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
alpha.disabled=".5">
<!-- host component -->
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.DropDownList")]
]]>
</fx:Metadata>
<s:states>
<s:State name="normal" />
<s:State name="open" />
<s:State name="disabled" />
</s:states>
<s:PopUpAnchor id="popUp" displayPopUp.normal="false" displayPopUp.open="true" includeIn="open"
left="0" right="0" top="0" bottom="0" itemDestructionPolicy="auto"
popUpPosition="below" popUpWidthMatchesAnchorWidth="true">
<!-- removed maxHeight! -->
<s:Group id="dropDown" minHeight="22">
<!-- border/fill -->
<s:Rect left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:SolidColorStroke color="0x5380D0" />
</s:stroke>
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Rect>
<s:Scroller left="0" top="0" right="0" bottom="0" focusEnabled="false" minViewportInset="1">
<s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="contentJustify"/>
</s:layout>
</s:DataGroup>
</s:Scroller>
<s:filters>
<s:DropShadowFilter blurX="20" blurY="20" distance="7" angle="90" alpha="0.45" color="0x6087CC" />
</s:filters>
</s:Group>
</s:PopUpAnchor>
<s:Button id="openButton" left="0" right="0" top="0" bottom="0" focusEnabled="false"
skinClass="spark.skins.spark.DropDownListButtonSkin" />
<s:Label id="labelDisplay" verticalAlign="middle" lineBreak="explicit"
mouseEnabled="false" mouseChildren="false"
left="7" right="30" top="2" bottom="2" width="75" verticalCenter="1" />
</s:Skin>
Sample Application
<?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">
<fx:Style>
#namespace mx "library://ns.adobe.com/flex/mx";
#namespace s "library://ns.adobe.com/flex/spark";
s|DropDownList
{
skinClass: ClassReference("VariableHeightDropDownListSkin");
}
</fx:Style>
<s:DropDownList labelField="name" horizontalCenter="0" verticalCenter="0">
<s:layout>
<s:VerticalLayout requestedRowCount="7"/>
</s:layout>
<s:dataProvider>
<mx:ArrayCollection>
<fx:Object name="one"/>
<fx:Object name="two"/>
<fx:Object name="three"/>
<fx:Object name="four"/>
<fx:Object name="five"/>
<fx:Object name="six"/>
<fx:Object name="seven"/>
</mx:ArrayCollection>
</s:dataProvider>
</s:DropDownList>
</s:Application>
Let me know if that helps,
Lance
viatropos answer will work, however you should try and avoid overriding an entire skin as much as possible.
In this case, you will notice that in viatropos's VariableHeightDropDownListSkin code that the Group where he removed the maxHeight attribute, there is also an "id" specified.
Now look at the documentation for DropDownList and you will notice in the SkinParts section that there is a "dropDown" skin part. This is actually a property of DropDownList.
So instead of overriding the skin, you can simply use actionscript (I use UIComponent.DEFAULT_MAX_HEIGHT here, but you can use whichever you wish):
(MyDropDownList.dropDown as UIComponent).maxHeight = UIComponent.DEFAULT_MAX_HEIGHT;
Unfortunately, this is a lot more complicated in Flex 4 than it was in Flex 3:
You should be able to define a layout for the DropDownList with a higher requestedRowCount (details here), but for > 6 rows you need to do more work (Flex issue SDK-25364).
in FB3 it's rowCount cause the dropdown is a descendant of a list control. FB4 is probably similar.
myDropdown.rowCount = 7;
I usually use something more like
myDropdown.rowCount = myDataProvider.lenght();

Resources