I just cannot understand why mouseEnabledWhereTransparent does not work on this skin.
The Skin this creates is basically a Button with a transparent background and a little triangle to the left side, like so: >ButtonText But the empty space around the Triangle does not receive mouse events.
I've tried wrapping another group around the triangle path and i've tried wrapping it into a Graphic Object, also without success. I could create a Rect with 0 alpha below everything, but isn't that exactly what mouseEnabledWhereTransparent should be doing for me?
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="21" minHeight="21" alpha.disabled="0.5"
mouseEnabledWhereTransparent="true">
<!-- host component -->
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<!-- states -->
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<!-- triangle tip -->
<s:Path data="M 0 0 L 0 14 L 10 7 L 0 0" bottom="5">
<s:fill>
<s:SolidColor color="0xFFFFFF" />
</s:fill>
</s:Path>
<!-- text -->
<s:Label id="labelDisplay"
textAlign="center"
verticalAlign="bottom"
maxDisplayedLines="1"
left="14" right="10" top="2" bottom="2" color="0x000000" fontSize="14">
</s:Label>
</s:SparkSkin>
Yo, what you need is to add a rectangle before that path to act as a hit area, this works:
<s:Rect left="0" right="0" top="0" bottom="0" >
<s:fill>
<s:SolidColor alpha="0" />
</s:fill>
</s:Rect>
This guy here has a good example of making custom buttons (minus the label)
mouseEnabledWhereTransparent has no effect if there are no mouse event listeners on the Group it is set on. In your example the Button object has a click event listener, but the Button's skin object (SparkSkin) does not.
From the ASDoc for GroupBase.mouseEnabledWhereTransparent:
"This property only goes in to effect if mouse, touch, or flash player gesture events are added to this instance."
A workaround for you would be to add a mouse event listener to the skin that won't do anything, for example:
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
mouseEnabledWhereTransparent="true" click="doNothing()">
<fx:Script>
<![CDATA[
protected function doNothing():void {
trace('doNothing');
}
]]>
</fx:Script>
...
</s:SparkSkin>
The main use case for this property has been adding click events directly to a Group, but it is interesting to think about the case you bring up. It might be reasonable to file an enhancement request along the lines of "Setting mouseEnabledWhereTransparent on a skin should have an effect if the hostComponent has mouse listeners attached".
Related
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" />
...
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>
I have implemented a chromeless windowedapplication in flex 4. But doing so i noticed that all the maximize, minimize and even the ability to drag the window around is gone. I need the ability to drag the window around. I have done a lot of googling and have been unable to come up with anything. Could somebody plz point me in the right direction.
Thanks in advance.
You'll have to create a custom skin for your WindowedApplication. If you look in the code of WindowedApplication, you'll find this:
[SkinPart (required="false")]
public var titleBar:TitleBar;
which means you can add a TitleBar to the skin, but you don't have to. As a matter of fact the default WindowedApplicationSkin doesn't have a titleBar.
Including a TitleBar in the custom skin will automatically give you the dragging behavior you're after. The default TitleBarSkin comes with the regular window buttons (minimize, maximize, close), so you may want to create a custom skin here too. One without the buttons if you don't need them.
Here's a stripped down example.
The custom skin for WindowedApplication (just a white background and a TitleBar):
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" >
<fx:Metadata>[HostComponent("Object")]</fx:Metadata>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
<s:State name="normalAndInactive" />
<s:State name="disabledAndInactive" />
</s:states>
<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0" >
<s:fill>
<s:SolidColor id="backgroundFill" color="0xffffff" />
</s:fill>
</s:Rect>
<s:TitleBar left="0" right="0" top="0" height="24"
skinClass="skin.TitleBarSkin" />
<s:Group id="contentGroup" left="0" right="0" top="25" bottom="0" />
</s:Skin>
The custom skin for your TitleBar (just a gradient background and a close button):
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
minHeight="24" >
<fx:Metadata>
[HostComponent("spark.components.windowClasses.TitleBar")]
</fx:Metadata>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
<s:State name="normalAndMaximized" />
<s:State name="disabledAndMaximized" />
</s:states>
<s:Rect id="background" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" />
<s:GradientEntry color="0xBABABA" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Button id="closeButton" label="close" right="0" verticalCenter="0" />
</s:Skin>
Apparently, the 'closeButton' is required, so you'll have to include it in the skin. But if you still want to get rid of it, just set its 'visible' and 'includeInLayout' properties to 'false'.
I need to round at only the top or bottom of a border container not all four corners, is their some CSS that I can use or do I have to create two new skins. I was reading their used to be a property for this for HBox back in the old days, is their not a property for BorderContainer now?
With BorderContainer you can't. However, the visual effect you want to achieve can easily be created with SkinnableContainer and a custom skin. In fact BorderContainer is just a specific form of SkinnableContainer.
So instead of BorferContainer create a SkinnableContainer with property 'skinClass':
<s:SkinnableContainer left="0" right="0" top="0" bottom="0"
skinClass="my.app.skins.TopRoundedCornerSkin">
<!--- your components go here --->
</s:SkinnableContainer>
Then create the skin class TopRoundedCornerSkin.mxml like so:
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("spark.components.SkinnableContainer")]
</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"
topLeftRadiusX="10" topLeftRadiusY="10"
topRightRadiusX="10" topRightRadiusY="10">
<s:fill>
<s:SolidColor color="0xffffff" />
</s:fill>
<s:stroke>
<s:SolidColorStroke color="0x000000" />
</s:stroke>
</s:Rect>
<s:Group id="contentGroup" left="10" right="10" top="10" bottom="10"
minWidth="0" minHeight="0" />
</s:Skin>
On the background rectangle, we set 4 radius properties to create the rounded corner you need.
I have a window in which I want to add/remove component and resize the window accordingly based on states. but for some reason it's ignoring the first resize.
here's a sample code
<?xml version="1.0" encoding="utf-8"?>
<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"
minWidth="450"
minHeight="355"
currentState="{stateBox.selected ? 'one' : 'two'}"
currentStateChange="handleStateChange(event.oldState, event.newState)">
<fx:Script>
<![CDATA[
private function handleStateChange(oldState:String, newState:String):void
{
if (oldState == "two") {
width -= 341;
minWidth = 450;
} else {
width += 341;
minWidth = 791;
}
}
]]>
</fx:Script>
<s:states>
<s:State name="one" />
<s:State name="two" />
</s:states>
<s:Rect id="rect1" top="0" left="0" right="0" right.two="341" bottom="0" >
<s:fill>
<s:SolidColor color="0xDDDDDD" />
</s:fill>
</s:Rect>
<s:Rect id="rect2" top="0" bottom="0" width="341" right="0" includeIn="two" >
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<s:CheckBox id="stateBox" label="change state" />
</s:WindowedApplication>
Idea is that when the state change to 'two', I want to add rect2 to display and increase the minWidth and size of the window. And when the state change to 'one', i want to remove rect2 from display and resize the window. This seems to work except the window doesn't shrink on the very first time the state change from "two" to "one" but works as expected afterwards. I'm not sure why it's ignoring first time I reduce the width. I also tried changing nativeWindow.bounds directly but that didn't work either.
Originally I just tried setting minWidth based on state (minWidth.one="450 minWidth.two="791") but that caused window to grow on left and shrink on right which caused the window to move left whenever the state changed. so then I just moved the window to right whenever state changed but that caused some flicker that I didn't want.
does anyone have any idea why this might be happening? or a good solution for my problem?
Try flipping these lines around from:
width -= 341;
minWidth = 450;
to:
minWidth = 450;
width -= 341;
I think the problem is with the way that condition is setup in general.... I'm going to copy your code and modify it how I would go about doing this and repost as an edit, but you could try the above suggestion (I believe you may be setting the width lower than the minimum width then reducing the minWidth so the setting of the width in the first place would have been set to a width that isn't valid according to the current minWidth, think you may only see this the first time around due to timing with validation.
EDIT(ed twice, add locking the window size by setting min and max heights equal to the set height):
<?xml version="1.0" encoding="utf-8"?>
<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"
minHeight="355"
maxHeight="355"
minWidth="450"
width.two="791"
width.one="450"
minWidth.one="450"
minWidth.two="791"
maxWidth.one="450"
maxWidth.two="791">
<fx:Script>
<![CDATA[
protected function stateBox_changeHandler(event:Event):void
{
// TODO Auto-generated method stub
currentState=stateBox.selected ? 'two' : 'one';
}
]]>
</fx:Script>
<s:states>
<s:State name="one"/>
<s:State name="two"/>
</s:states>
<s:HGroup width="100%"
height="100%"
gap="0">
<s:Rect width="450"
height="100%">
<s:fill>
<s:SolidColor color="0xff0000"/>
</s:fill>
</s:Rect>
<s:Rect width="341"
height="100%"
includeIn="two">
<s:fill>
<s:SolidColor color="0x000000"/>
</s:fill>
</s:Rect>
</s:HGroup>
<s:CheckBox id="stateBox"
label="change state"
change="stateBox_changeHandler(event)"/>
</s:WindowedApplication>
Does this achieve the desired behavior ^ (sorry I know I changed a lot of code but this is just how I would approach it, maybe this won't work because of other explicit sizing you need to set but seems to achieve the goal to me)