Scroller acting different regarding his first child - actionscript-3

im' facing a strange issue with Scroller in my application.
I'm using for my forms scrollers like this :
<s:Group id="mainGrp" width="100%" height="100%" >
<s:Scroller id="scroller" width="100%" bottom="50" top="30" >
<s:Group id="childrenGrp" width="100%" height="100%" >
<s:VGroup width="100%" height="100%" paddingTop="15" paddingLeft="20" gap="20" paddingRight="10" paddingBottom="10">
</s:VGroup>
</s:Group>
</s:Scroller>
</s:Group>
With this example, my scroll bar (with mouse wheel) is quite slow. If i remove the container Group with id "childrenGrp", i 've got a normal speed but the padding on the Vgroup make the scroller in some strange state (impossible to go to the top and the bottom of the container).
My questions are :
1/ Why the scroll speed change regarding scroller's first child ? (group make it slow, and vgroup is normal)
2/Why paddingTop and paddingBottom on scroller's first child make the scroller unusable ?
Thx in advance.

For number 1 I don't have an exact answer, but you could try this: Capture the mousewheel event and trace the event.delta (the amount of lines the mousewheel scroll moves the bar)
protected function foo_mouseWheelHandler(event:MouseEvent):void
{
trace(event.delta);
}
Is the amount different on both cases (with or without the group)

Related

Scroll bars disappear when switching between interaction modes?

I have an application that switches between touch and mouse interactions. On a as needed basis I change between the two. However, when I switch from touch to mouse the scroll bars have disappeared.
It seems like a bug. I'll post an example soon but basically just switch between modes:
scroller.setStyle("interactionMode", "touch");
// later:
scroller.setStyle("interactionMode", "mouse");
// scrollers are invisible after this call
Example code:
<s:Scroller id="myScroller" top="20" right="40">
<s:Group height="100" width="100">
<s:Rect width="100" height="400">
<s:fill>
<s:SolidColor color="red"/>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="blue" weight="2"/>
</s:stroke>
</s:Rect>
</s:Group>
</s:Scroller>
ActionScript:
protected function button1_clickHandler(event:MouseEvent):void
{
if (myScroller.getStyle("interactionMode")=="mouse") {
myScroller.setStyle("interactionMode", "touch");
}
else {
myScroller.setStyle("interactionMode", "mouse");
}
}
You have to click down on the scroller and move it while it's in touch mode and then the scrollers disappear and don't reappear.
The visible and includeInLayout properties are both true after setting back to mouse.
It looks like it has to do with some skin parts being reused but not being reset. From the Scroller design documents:
The first time Scroller detects it needs to display a ScrollBar it
will ensure one exists
Scroller detects that it needs to display ScrollBar at beginning of touch interaction mode or at skin attach time if interaction mode
is anything but "touch"
If the legacy ScrollBar part already exists, the Scroller will use that one else the ScrollBar will create an instance from the factory part, set the instance to the corresponding non-factory part and call
partAdded() for it.
For example Scroller will create an instance from
the horizontalScrollBarFactory part and will set horizontalScrollBar
to that instance with partAdded() being called.
I've looked at all the scrollbar parts and scale, visible and includeInLayout are all true or 1. So, it seems the only way is to force it to recreate the parts.
The below is a work around. It changes the skins, validates and then changes back to the original skin:
if (myScroller.getStyle("interactionMode")=="mouse") {
myScroller.setStyle("interactionMode", "touch");
}
else {
myScroller.setStyle("interactionMode", "mouse");
myScroller.setStyle("skinClass", skins.MinimalScrollerSkin);
myScroller.validateNow();
myScroller.setStyle("skinClass", spark.skins.spark.ScrollerSkin);
}

How to continuously update an image based on contentHeight?

I'm trying to draw a solid background color behind an image. The image is a banner that is to take up 33% of the top of my canvas unless that puts it outside of it's aspect ratio. That's where the background color comes in; the background color fills in the right-side of what's remaining after the image fills in it's maximum width without breaking outside of it's 33% height or aspect ratio.
My problem is, with the code below, it only checks the contentHeight once and therefore, if the image height is reduced below what was initially loaded, my background color can be seen below the image (undesired). I can't use my image height since sometimes the height of my image exceeds what is actually shown (because of maintainAspectRatio).
Does anyone know how to obtain a consistent (and bindable) height of the image at all times that is matched to the content and not the container?
I could fully accept that I'm approaching this the wrong way as well so any alternatives to this method that have the same desired result would be much appreciated.
Component:
<mx:Canvas id="mainCanvas" width="100%" height="100%">
<mx:HBox x="0" y="0" backgroundColor="{myBgColor}" width="100%" height="{Math.min(myImg.contentHeight, mainCanvas.height * 0.33)}" />
<mx:Image id="myImg" source="{myImageSrc}" maintainAspectRatio="true" width="100%" height="33%"/>
</mx:Canvas>
My (untested) suggestion is to use the complete handler of Image (spark, not mx):
<fx:Script>
<![CDATA[
function myComplete(event:Event) {
myBox.height = Math.min(myImg.contentHeight, mainCanvas.height * 0.33);
}
]]>
</fx:Script>
<mx:Canvas id="mainCanvas" width="100%" height="100%">
<mx:HBox id="myBox" x="0" y="0" backgroundColor="{myBgColor}" width="100%" />
<s:Image id="myImg" complete="myComplete(event)" source="{myImageSrc}" maintainAspectRatio="true" width="100%" height="33%"/>
</mx:Canvas>
Also I don't understand why you use HBox and not Image's backgroundColor...
Eventually had to use a resize handler on my image since the complete handler never fired for my embedded image source. I was limited to using Flex 3 so no spark components are available.
Solution below:
protected function resizeHandler(event:ResizeEvent):void
{
var newHeight = Math.round(Math.min(myImg.contentHeight, mainCanvas.height * 0.33)) - 1; // Magic -1 because image had a bottom white padding
blueBg.height = newHeight;
}

placing labels dynamically

In my .mxml file, I am populating two side by side Labels with text data from a database.
Like this:
<s:Label x="10" y="37.5" width="100%" text="{data.city}"/>
<s:Label x="86" y="36.75" width="100%" text="{data.state}"/>
Sometimes, I will get a particularly long piece of text data and this will cause the 2 labels to overlap each other and become totally unreadable.
I think this is happening because I have the x and y set. Is there a way to make this more dynamic?
Thanks!
I would recommend exploring different Flex layout containers.
HGroup
<s:HGroup>
<s:Label text="{data.city}"/>
<s:Label text="{data.state}"/>
</s:HGroup>
This provides the kind of layout it sounds like you're looking for from your example. However, you may also want to look at a few other containers Flex offers.
Form
Flex forms align data in ways that are often useful for creating, well, forms. You may want to consider this for your UI, especially if you're allowing a user to give input that persists back to your DB.
<s:Form>
<s:FormItem label="City:">
<s:Label text="{data.city}"/>
</s:FormItem>
<s:FormItem label="State:">
<s:Label text="{data.state}"/>
</s:FormItem>
</s:Form>
You could do a couple of things:
If you have a function that gets called to set the values of each label, reposition the labels based on the contents in that function.
If the values for the labels are bound to data so that you don't necessarily get notified when the data is refreshed, then it's time to override the updateDisplayList() method of UIComponent, and have it reposition your labels there.
There is a lot of efficiency that can be gained (which will improve your performance) by understanding and using the life-cycle of a UIComponent. There's lots of good info on the subject out there if you just google "Flex component lifecycle"
Good luck!
if you have to display your labels in a limited width, then you can use maxWidth property of labels, this will display your text in label, and if text is long then it will show some text and remaining in ... format.
<s:Label text="{data.city}" maxWidth="150"/>
Try set X of second label with the width of the first label + space + x first label.
So: first label width + space + x of first label

Spark datagrid columns issue

I have a spark Datagrid with lot of columns. The problem is that if i have a long text in a cell, then the text goes over other columns.
Any ideas how to fix this? I want the text to stay in it cell, if it longer than the columns width, then the text to be truncated somehow.
Thank You
Try making a custom item renderer for the columns that are spilling over, and add a tooltip to when you hover the mouse, you can see the entire cell contents:
<s:GridColumn dataField="dataFieldName">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer >
<s:Label toolTip="{data.dataFieldName}" text="{data.dataFieldName}"/>
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>

ActionScript: manually scrolling a element wrapped inside a Scroller window

The answer to my question is possibly easy, yet I haven't found an example of solving it in the web, nor have I found a solution reading ActionScript reference.
My problem is the following: I have a big UIComponent derivate element inside a Scroller (spark.components.Scroller) window. The Scroller class is great because when my canvas element, that changes size dynamically, exceeds its boundaries, scrollbars appear automatically and handle scrolling of my UIComponent inside it.
However, I'd like not just to be able to Scroll using these automatically appeared scroll bars, but also by using a pan tool that I will myself implement (similar to the hand tool in Adobe software, for example). The thing is that I am not able to modify correctly the element's position inside the Scroller window.
I tried, as a first approach, accessing to my elements' 'x' and 'y' properties, however, when changing them, I dont get the resulkts wanted. The code for it is the following (in which, for symplifying reasons, I used a text label as my 'inside' element, and two buttons as an external scroll controller, instead of a hand tool)
Tests.mxml
<fx:Script>
<![CDATA[
protected function der_clickHandler(event:MouseEvent):void
{
text.x += 5;
}
protected function izq_clickHandler(event:MouseEvent):void
{
text.x -= 5;
}
]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>
<s:Scroller id="sc" x="50" y="50" width="200" height="100">
<s:Group width="100%" height="100%">
<s:Label id="text" width="400" height="10" x="50" y="50" text="blebleblebleblebleblebleblebleblebleblebleble"/>
</s:Group>
</s:Scroller>
<s:Button id="der" x="154" y="182" label="->" click="der_clickHandler(event)"/>
<s:Button id="izq" x="76" y="182" label="<-" click="izq_clickHandler(event)"/>
</s:Application>
And a link to a compiled version, to see what I'm speaking about:
http://megaswf.com/file/1135821
(press 'view fullscreen' if you can't see it)
Help would be really appreciated, as I've been stuck all afternoon with this, and really need it for my project :S
Anyway, many thanks in advance, and regards!
I managed to solve it! (This is the second time this week that I solve something just after posting it here :D).
The property that I had to change is sc.viewport.horizontalScrollPosition+=5; instead of the internal elements 'x' position. And the same for vertical pos.