ActionScript: manually scrolling a element wrapped inside a Scroller window - actionscript-3

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.

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;
}

How to vertically align to top in a textinput (as3)?

I have the following code (textinput).
<s:TextInput id="label"
text="just testing"
width="100%"
height="200"
contentBackgroundColor="#aaaaaa"
styleName="normalText">
</s:TextInput>
I am having a hard time finding how to align the text ("just testing") to the top.
I checked the Adobe documentation but it seems like there is no vertical alignment property available for this property.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/TextInput.html
I realize that there is a textarea component available but due to performance reasons, I need to use textinput.
topPadding seems to work for mx
<mx:TextInput
id="txt"
paddingTop="5"
text="I am Vertically aligned text"
textAlign="center"
width="250"
height="250">
</mx:TextInput>
Any tips would be greatly appreciated.
Thanks!
Quick version
If the font size never varies, it may suffice to just work with paddingBottom. Because by default the vertical alignment is set to middle, decreasing paddingTop alone will not suffice to move the text up sufficiently; it's set to 1px by default anyway. You'll have to increase paddingBottom too. I cannot give you exact numbers: it depends on the size of the font, so you'll have to play around with the values a bit.
<s:TextInput paddingBottom="6"/>
Reusable version
If you want your solution to be reusable with any kind of font, you'll have to create a custom skin for TextInput. Fortunately, that's not too hard:
Find the spark.skins.spark.TextInputSkin
Copy it and give it a new name, say my.skins.TopTextInputSkin
Find the RichEditableText tag with id textDisplay (it's at the bottom)
Set its verticalAlign property to top
Apply the new skin: <s:TextInput skinClass="my.skins.TopTextInputSkin"/>

Scroller acting different regarding his first child

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)

How to use Actionscript to specify Flex "fit to content"

Flex Builder defaults some components to "fit to content" if you don't specify a set width or height. I'm trying to fill a mx:Tile component with Actionscript, but the layout has some strange spacing when I don't specify the width of a component I add to it. Is there a way to set the components to "fit to content" using Actionscript?
Do you still need the tiles to align in columns/rows, or do you want them all to be fit-to-content? If you want the former, good luck, and I hope someone else can answer for my benefit. If you want the latter, you could use FlowContainer (which I got from Appdivision).
// AS3 way
var c:UIComponent = <your component that should fit into parent's content>;
c.percentWidth = 100;
c.percentHeight = 100;
// MXML way
<mx:Canvas>
<mx:Button id="c" width="100%" height="100%"/>
</mx:Canvas>