keydown in flex Flex - apache-flex

I have an small application in flex in which I have defined 2 canvases. On one of them I added controls and the other one is used to draw something and no controls are added:
<mx:Canvas x="0" y="80" width="100%" height="520%" id="Canvas1"/>
<mx:Canvas x="0" y="0" width="100%" height="80" id="Canvas2"/>
I add an keydown event handled to the application but it is triggered only after I click with the mouse on the first Canvas(the one where controls have been added). Otherwise the event is not triggered when keys are presses.
I've tried several things: to set focus on the second canvas, to add the keydown handler to the application(this),stage, canvas... Unfortunately I didn't find a solution to trigger keydown no matter where the focus is.

This is for flex 4.
<?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"
name="MyApp"
width="480" height="480"
creationComplete="init();">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
public function init():void
{
trace("init");
this.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
}
private function keyDown(event:KeyboardEvent):void
{
trace(event.charCode);
}
</fx:Script></s:Application>

The first problem you describe (having to click the mouse before any KeyboardEvents are dispatched) is likely due to the browser not giving focus to the Flex application itself. You can use Javascript in the HTML wrapper to programmatically give focus to the Flex app on the "body" element's "onLoad" event. I know for certain this works in Firefox and I believe it works okay in IE as well. I'll try to dig up the relevant Javascript code.
As far as the second problem, have tried adding an event listener to Application.application for catching all KeyboardEvents?

Related

Flex / ActionScript - Click Through An Element To Application Behind Air App

I'm attempting to build a desktop AIR app using flex/Action Script in Flash Builder.
My desired functionality is this:
- transparent background
- semitransparent (alpha 0.5) item/element that ignores all mouse events and "passes clicks through" to the application behind the app
So essentially what I want to have is that the element handles mouse events in exactly the same way a transparent background does - ie. it is like you're clicking on the application behind
Here is a code example of what I have tried. In the below example clicking on the button fires the "window clicked" alert to demonstrate that the click is being ignored by the button and reaching the window with the transparent background. When I remove the click handler though, clicking on the button does not result in the click being passed through to application behind, like a click anywhere else on the transparent background does.
Any ideas?
<?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"
alwaysInFront="true"
creationComplete="maximize();">
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
s|WindowedApplication
{
skinClass:ClassReference("spark.skins.spark.SparkChromeWindowedApplicationSkin");
background-color:#999999;
background-alpha:"0";
}
</fx:Style>
<fx:Script>
import mx.controls.Alert;
public function windowClicked():void{
Alert.show("window clicked");
}
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Window id="mainWindow" height="100%" width="100%" mouseChildren="false" backgroundAlpha="0">
<s:Button label="Click Through Me Please" alpha="0.5"/>
</s:Window>
</s:WindowedApplication>
I made a quick comment to your question but thought I would elaborate in an answer.
Since I'm sure you are going to do more than your example up there, here is how those properties work:
mouseEnabled="false" - this says you can't click me but you can click my children. This works well when you are disabling a single item or want click event to pass through an item to it's children.
mouseChildren="false" - this says you can't click my children. This is useful if you are goin to build complex overlays in your app that might contain 10 display objects and want want the mouse to ignore them all.
Hope this helps!

Inconsistent Flex Effects

I've created a simple effect in Flex, code below, but it does not execute correctly... When I rollOver the icon, MOST of the time the effect plays, and when I rollOut of the image the effect should play in reverse, but rarely does...
Is my code or logic incorrect? FYI - I'm using Flash Builder 4.6.
<?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" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:Move id="detail_fade" target="{detail_panel}" xFrom="218" xTo="400" />
</fx:Declarations>
<s:Panel id="detail_panel" x="218" y="10" width="728" height="580" title="something">
</s:Panel>
<s:VGroup x="7" y="5" width="200" height="200">
<s:Image source="images/Airfield Icon.jpg"
rollOver="detail_fade.play()" rollOut="detail_fade.reverse()"/>
</s:VGroup>
As Mahesh pointed out in his comment, reverse() will only reverse an effect that is actually playing. Which is why you only see it happening sometimes: i.e. when you're quick enough to roll_out before the effect has ended.
You should instead use:
detail_fade.play(null, true);
The first argument of the play method, is an Array of the targets of your effect. Since you've already given it a target, you don't need to pass it again (that's why it says null).
The second argument is a Boolean telling the effect to play in the inverse direction if set to true. It is of course false by default.
Now, you may notice that when you roll_out quickly, the effect will jump to the end and start playing in the other direction from there.
This can be fixed like so:
if (detail_fade.isPlaying) detail_fade.reverse();
else detail_fade.play(null, true);

Text in TextArea on AIR mobile app disappears after displaying for a moment

I'm having a very odd issue where I am trying to use a text area to display some text on a mobile AIR app. It works fine whenever I am using the phone emulator on my desktop to debug, however whenever I put the app on my phone, the text displays, then disappears. I've also noticed that if I lock the screen and unlock, the text will display just fine when I come back.
Here's the code:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Program Overview">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
private var text:String = "Hey how are ya";
]]>
</fx:Script>
<s:TextArea text="{text}" editable="false" />
</s:View>
One other interesting thing to note is that it only happens on certain Views, and only on Views in the first ViewNavigator tab. This leads me to believe that there isn't really anything wrong with my use of the TextArea, but something else happening at a higher level in the application. Any ideas on what I should look for?
I think than the problem can be solved if you add the skinClass:
this is for TextArea:
<s:TextArea id="text1" skinClass="spark.skins.mobile.TextAreaSkin" text="{myVar}"/>
this is fot TextInput:
<s:TextInput id="text2" skinClass="spark.skins.mobile.TextInputSkin" text="{myVar}"/>
I hope this help you!
I ended up replacing all of my TextArea's with StyleableTextFields as #Al_Birdy suggested and that took care of the issue. Because you can only use them in AS it made layout and styling a little bit more difficult but it was definitely worth the fix.

Handling depth with Flex 4

I have a code in Flex 4 like this
<!-- START >>> middle part: items -->
<mx:Canvas id="itemContainer"
width="100%"
height="100%">
<!-- START >>> Items Display on the page -->
<mx:Repeater id="richTextReapeater"
dataProvider="{_model.current_day.richTextNotes}">
<components:RichTextNoteDisplay theNote="{richTextReapeater.currentItem}" />
</mx:Repeater>
<mx:Repeater id="postItReapeater"
dataProvider="{_model.current_day.positNotes}">
<components:PostItNoteDisplay theNote="{postItReapeater.currentItem}" />
</mx:Repeater>
......
</mx:Canvas>
Mainly it's a MX:Canvas that has inside it reapeaters for multiple custom components I created. Most of these custom components are like this:
<s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
x="{theNote.x}"
y="{theNote.y}"
width="{theNote.width}"
height="{theNote.height}"
depth="{theNote.depth}"
rotation="{theNote.rotation}"
creationComplete="skinnablecontainer1_creationCompleteHandler(event)" >
Everything works fine (x,y,width,height,rotation) except for depth!
it seems that regardless what the number is it shows as the order it was rendered in the parent container. (MX:Canvas)!
What I want to acheive is that relative to each others, all the items in the mx:Canvas shows in the order of "depth" assigned to them.
How do I do this?
You're using a repeater; which is, in essence, a loop.
It sounds like you're asking to loop over items, but process those items in a different order. Is that correct?
My first recommendation would be that you look into ways to sort your dataProvider items by depth before the repeater 'runs'.
My second recommendation is that you don't use a repeater. A List based class will give you better performance due to renderer recycling.
If you really need to create all children at once, my third recommendation is that you move to an ActionScript implementation which will give you lots more granular control over how and when things are created.
Everytime I've used a repeater I've been unhappy.
Here is some info on lists and itemRenderers with Flex 4.
This is a rough estimate of how I might modify this sample to use a list instead of a repeater:
<!-- START >>> middle part: items -->
<mx:Canvas id="itemContainer"
width="100%"
height="100%">
<!-- START >>> Items Display on the page -->
<s:List id="richTextList"
dataProvider="{_model.current_day.richTextNotes}"
itemRenderer="com.something.myComponent">
</s:List>
</mx:Canvas>
An itemRenderer may be something like this:
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:SkinnableContainer rotation="{data.rotation}"
creationComplete="skinnablecontainer1_creationCompleteHandler(event)" />
</s:ItemRenderer>
The list will determine the width, x, and y positions of the renderer. In most cases it will also determine the height; although the Flex 3 List has a variableRowHeight option.
If you want to use a different renderer based ond ata, look into using an itemRendererFunction

How to deal with competing effects in Flex?

I'm a beginner at Flex, and having the hardest time, working with Effects.
Right now I'm dealing with the problems faced when dealing with competing effects.
Please look at the following code. I have basically created a short reproducible tests sample which shows the problem I'm facing:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="400">
<mx:Script>
<![CDATA[
private function showmenu():void
{Menu.visible= true;
}
private function hidemenu():void
{Menu.visible= false;
}
]]>
</mx:Script>
<mx:WipeDown id="wipedown" duration="900"/>
<mx:WipeUp id="wipeUp" duration="900" />
<mx:Canvas id="main" width="400" height="400"
rollOver="showmenu();" rollOut="hidemenu();">
<mx:Button label="Show Menu"
x="100" y="20">
</mx:Button>
<mx:Canvas id="Menu" visible="false"
width="100" height="200"
backgroundColor="#B8B8B8" x="96" y="35"
showEffect="{wipedown}" hideEffect="{wipeUp}">
</mx:Canvas>
</mx:Canvas>
</mx:Application>
This basically shows a Button, and when you roll over on the button, another canvas, which is going to be a sort of menu, will be displayed. When you roll out, the Menu disappears.
The menu also has some effects, and if you try to start one effect before another is over, it gets into an infinite loop.
To reproduce what I am talking about, rollover the button, and then rollout and then quickly rollover again. You will see that the menu effects get stuck in a loop.
How do I code around this?
If you're having problems with events playing when they shouldn't, just add EffectEvent.EFFECT_START listeners to your events and use it to stop any playing events. e.g,
function _handleEffectStart(e:EffectEvent):void {
if(e.target == wipedown) {
wipeup.stop();
} else {
wipedown.stop();
}
}
Or something similar.
I cannot reproduce your problem. No matter where/when I move my mouse in or out, it never goes into a loop. Note that I'm using Flex 3.2. Maybe it depends on which version your using?
Btw, your code doesn't completely match your description: You have the rollOver and rollOut events on the canvas that also contains the canvas that you are showing and hiding. Just a guess, but I can imagine that the effect itself actually causes your mouse to be over or not over the canvas anymore, triggering the rollOver/rollOut, which then again cause the mouse to move in/out... Is that the infinite loop you're experiencing?

Resources