How do I trigger an update in a Callout to update it's position after it's content has been resized? - apache-flex

I have a Callout whose content is resized by certain user interactions. The skin has an animation and after that the Callout is no longer positioned correctly and needs to be repositioned.
Is there any way to invalidate the Callout after the Callout content has been resized?

It was simpler than I thought. I added an event handler to the resize event on the Callout content and then in that event called the Callout method updatePopUpPosition() to update the Callout position, obviously.
At first I was looking for one event that I could listen for after the Callout had been resized but that would involve dispatching a custom event when there is an effect. Adding an event handler for resize triggers multiple times when the resize effect is running but the animation and positioning is flawless so I'm keeping it.
<?xml version="1.0" encoding="utf-8"?>
<s:Callout 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:Script>
<![CDATA[
import mx.events.FlexMouseEvent;
import mx.events.ResizeEvent;
protected function editorBar_resizeHandler(event:ResizeEvent):void {
updatePopUpPosition();
}
]]>
</fx:Script>
<controls:MyContent id="editBar" width="100%" resize="editBar_resizeHandler(event)" />
</s:Callout>

Related

Fill entire content with a background image in Flex/spark

I created a 960x640px image which i want to use as background picture for any type of mobile device by scalling the image to the device s resolution.
How can i achieve this?
i tried:
<?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="MainView">
<s:Image width="100%" height="100%" fillMode="scale" scaleMode="stretch"
source="assets/background.jpg" />
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:View>
This looks good in the design view, it fill the whole screen but when i run the application everyting is really messy (the image is a lot smaller or a lot bigger than the mobile emulator screen)
Is there a better way to do this? Is it possbile to set a background-image directly on the view?
Thanks
set the fillMode="repeat"
this will repeat the image to fill the view

Placing Flex-component in the middle of the screen

I have a very general question and have prepared a simple test case.
When using BasicLayout (i.e. absolute positioning) - what is the best approach to place a Flex component in the center of the application?
In the test case below I'm using x="{width/2}" but this gives me at least 2 problems:
How do I account for the component dimensions (the ProgressBar in the test case)?
Is the binding {width/2} a good idea to use? Wouldn't it send unnecessary DATA_CHANGE events in some cases?
And finally I wonder, how this all applies to full screen applications using StageScaleMode.SHOW_ALL - because currently my application is aligned to the top-left in the full screen mode and there is a white dead zone on the right of it. (Which is at least a change from pure Flash/AS3 behaviour, where the full screen content is displayed in the center of the screen and 2 dead zones on the left and right).
<?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"
width="700" height="525"
backgroundColor="#CCFFCC"
initialize="systemManager.stage.scaleMode=StageScaleMode.SHOW_ALL">
<fx:Script>
<![CDATA[
private function fullScreen(event:MouseEvent):void {
stage.displayState =
stage.displayState == StageDisplayState.NORMAL ?
StageDisplayState.FULL_SCREEN :
StageDisplayState.NORMAL;
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="connected" />
</s:states>
<s:CheckBox right="10" bottom="10"
label="Full screen"
click="fullScreen(event)" />
<mx:ProgressBar indeterminate="true"
x="{width/2}" y="{height/2}"
label="Connecting..." labelPlacement="center"
includeIn="normal" />
</s:Application>
Way easier than that: just use horizontalCenter and verticalCenter properties of UIComponent. When used inside a BasicLayout the component will always be centered. Like this:
<mx:ProgressBar indeterminate="true"
horizontalCenter="0" verticalCenter="0"
label="Connecting..." labelPlacement="center" />
If you give these properties a value other than '0' the component will be offset from the middle by the amount of pixels you specify as a value. (e.g. horizontalCenter="50" will offset the component 50 pixels to the right of the center of the parent component)
That white space is probably due to your usage of systemManager.stage.scaleMode=StageScaleMode.SHOW_ALL. Just remove that line. Why are you doing that anyway?
edit
Just noticed you're using a fixed 'width' and 'height' on your Application: you'll have to make those '100%' if you want your app to really fill the screen. This is another possible cause for that white space.
To get your application centered (rather than left/right aligned) when using systemManager.stage.scaleMode=StageScaleMode.SHOW_ALL, set systemManager.stage.align to the empty string - i.e.:
// in your Application creationComplete handler
systemManager.stage.scaleMode = StageScaleMode.SHOW_ALL;
systemManager.stage.align = "";
I typically do 2 things,
I place objects inside VGroups/HGroups with alignment, I also use relative widths eg percentages.
Think like in the old days of using HTML tables. It works very well especially if your canvas is resized allot.
All of my canvases have to be resizeable as I like to only write my apps once, for pc, mobile etc, so I just make everything scalable by default.

Restrict mouse move area in a flex application

In my flex application I need to restrict the mouse from moving in a certain area.In other words I want to create a 'No Entry Zone' for the mouse in the application.Hiding the cursor when mouse enters the area is not a solution for me.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600">
<mx:Script>
<![CDATA[
protected function canvas2_mouseMoveHandler(event:MouseEvent):void
{
trace('mouse moved inside');//this trace should not be executed.
}
]]>
</mx:Script>
<mx:Canvas x="250" y="180" backgroundColor="white" height="300" width="400" mouseMove="canvas2_mouseMoveHandler(event)">
<mx:Text text="Mouse Entry not allowed"/>
</mx:Canvas>
</mx:Application>
You cannot programatically position (so neither fix) the mouse cursor in Flex (as pointed out by Alex Harui in this answer).
Although, you could give a try to this approach.
By tracking the mouse's x|y you could
draw the cursor at its last enabled
position when entering your
restricted canvas (+ hide it), and
remove the drawn cursor on
mouseOut event (+ show the cursor).
For restricting the drag / drop in your Canvas you just set the dragEnter property (event handler) on it:
dragEnter="event.stopImmediatePropagation();"
You can see some samples of enabling and disabling drag/drop operations here
We can not control/set Mouse position From Flex/ActionScript
but we can make Canvas Mouse in-sense-able applying properties
i.e. when we move mouse over it would not fires an event. properties are
mouseChildren="false"
mouseEnabled="false"
Hopes that helps

Components inside a repeater not resizing as expected

I have an mxml panel in which I'm using a repeater. The panel can be resized horizontally and I would like for the repeated components to resize together with panel. Here is a simplified example of how things look like:
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" ...>
<!-- scripts and some controls -->
<mx:VBox width="100%">
<core:Repeater width="100%" dataProvider="model">
<ns1:MyItemRenderer width="100%" />
</core:Repeater>
</mx:VBox>
</mx:TitleWindow>
When I resize the component, the width of the repeated items does not change.
There also buttons and event handlers, which add and remove items from the model. When this is done, the repeater updates to display the correct number of items and all the items are resized correctly.
I have not been able to get the items to resize when the root panel is resized. I can see, that the VBOx around the repeater is getting a resize event. However, the repeated items are not getting the event. I tried to dispatch a resize event to the repeated items manually from a resize handler I hooked up to the VBox but that didn't help.
I also tried adding and removing a dummy-item from the ArrayCollection which is the dataProvider (because that triggers a correct resize otherwise as mentioned above) However, doing this in the resize handler of the VBox just leads to the repeater not showing any items at all.
Is there any way to get items in a repeater to resize with their enclosing container?
The ItemRenderer I'm using resizes correctly when used in a mx:List. It is built so it can work both with the data property set by the List container an getRepeaterItem() when used in a Repeater. In this particular case, I cannot use the List as a container because of the way it behaves with regards to controlling its height via the rowCount, height and maxHeight properties which doesn't work out for me in this particular case (I spare you the details).
override updateDisplayList in the titleWindow and when the height or width changes, invalidate the displayList on every item created inside the repeater.
That said, using repeaters are generally considered bad practice because every component inside it is rendered. A list based class--which makes use of renderer recyling is considered to be much more performant.
Based on your code segment, I can't tell whether your code could be re-worked without repeaters, or not.
For the record, I figured out the following "solution":
Use the maxHeight attribute on the box enclosing the repeater, binding it to an expression that derives the correct value from the other components... I still need to hardcode any space I want to reserve for components that come after the box containing the repeater if I don't want to have them pushed out of the enclosing panel but it is good enough for now.
essentially:
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" ...>
<!-- scripts and some controls -->
<mx:VBox id="outerBox" height="100%">
<mx:VBox id="innerBox" width="100%"
maxHeight="{outerBox.height - innerBox.y - 40}">
<!-- reserve 40 px for the button -->
<core:Repeater width="100%" dataProvider="model">
<ns1:MyItemRenderer width="100%" />
</core:Repeater>
</mx:VBox>
<mx:Button label="Stay Visible"/>
</mx:VBox>
</mx:TitleWindow>

Track mouse position repeatedly in flex application

I have a container Canvas named "cnvList" which contains another component horizontal list "hlist". When i hover the mouse over "cnvList", it should display the current mouse position relative to the container cnvList. I have used cnvList.contentMouseX for this. But it should repeatedly track the mouse position repeatedly even when the mouse is not movedk. Can anyone suggest me with code how it can be done?
Try using the Event.ENTER_FRAME (enterFrame) event on the Canvas, let me know if that does it.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">
<mx:Canvas id="cnvList" width="100%" height="100%"
enterFrame="trace(cnvList.contentMouseX)">
<mx:HBox id="hlist" width="100%" height="100%"/>
</mx:Canvas>
</mx:Application>
Alternatively you try "mouseMove" instead of "enterFrame" to get a trace only when the mouse is moved. You can also add an event listener to Application.application or even the stage itself to get notification when the mouse is moved anywhere in the app.

Resources