Flex: Scrolling in datagrids - apache-flex

I have 2 questions about flex datagrids:
How can I scroll it automatically to the bottom when new portion of data arrived to it (e.g. I added new items)
Strange, but seems it doesn't scroll when I use scrolling wheel, is there any trick about it (especially for mac Users)
Thanks in advance
Some changes:
public function scroll():void
{
trace(chatboard.maxVerticalScrollPosition);
chatboard.verticalScrollPosition = chatboard.maxVerticalScrollPosition;
}
<mx:TextArea id="chatboard" x="10" y="10" width="310" height="181" text="{chatMessages}" editable="false" verticalScrollPolicy="on" resize="scroll()"/>
But actually it don't help. The text area is not autoscrolled :(
Seems that 1) scroll is not called after new string is added to chatMessages

I find here that the mouse wheel scrolls the text area by default. Are you looking for a different behavior?
As far as skipping to the end goes:
in your TextArea wire up to the updateComplete and it seems to work as you would like:
<mx:TextArea id="textArea1" liveScrolling="true" updateComplete="textArea1_Changed(event);" />
then
private function textArea1_Changed(event:Event):void {textArea1.verticalScrollPosition = textArea1.maxVerticalScrollPosition;}
finally, you can test with something like:
private function btnClick(e:Event):void{textArea1.text += new Date().getTime().toString() + "\n";}

1) dataGrid.verticalScrollPosition=dataGrid.maxVerticalScrollPosition

Related

Smooth scrolling a Spark List with variable height items using the mouse wheel

We have a list of variable height items that we display in a Spark List control. When the user clicks and drags the vertical scrollbar the list scrolls smoothly. When the up/down arrows are used it moves in small and discrete steps. When the mouse wheel is used the list scrolls in very large discrete steps that is problematic for the user.
We would like to enable smooth scrolling for the mouse wheel. The height of our items vary significantly and it is easy to get lost when you scroll with the moouse due to the discrete scrolling.
Our implementation is fairly simple:
<s:List id="chartList"
dataProvider="{pm.charts}"
itemRenderer="charts.ChartItemRenderer"
horizontalScrollPolicy="off"
verticalScrollPolicy="on"
useVirtualLayout="false"
cachePolicy="auto">
</s:List>
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="false"
xmlns:charts="charts.*"
>
<fx:Script>
<![CDATA[
private var _canvas:BitmapData;
public function set canvas(value:BitmapData):void
{
_canvas = value;
}
[Bindable]
public function get canvas():BitmapData
{
return _canvas;
}
public function render(x:int,y:int, data:int):void
{
_canvas.draw(this);
}
]]>
</fx:Script>
<charts:DefaultChartContainer
chart="{data}"
cachePolicy="on"/>
</s:ItemRenderer>
There does not appear to be an out of the box method for implementing smooth scrolling in a Spark List. How would one go about implementing smooth scrolling in a spark list for variable height items?
Edit:
Here is another way to do this:
http://forums.adobe.com/message/3844410#3844410
Ok, so this wont be easy, but it is doable.
1) Create a custom skin for your list
2) In the custom skin, replace the scroller with a custom scroller (MyScroller)
3) Create a new class that extends Scroller, called MyScroller
4) Adobe in their infinite wisdom made skin_mouseWheelHandler private - which they seem to do all over the place, so you would have to override something higher up, maybe attachSkin and detachSkin. Or you could try adding your own skin_mouseWheelHandler with a higher priority in attachSkin and prevent default on it so the default does not get called.
5) Replicate the code in skin_mouseWheelHandler, and modify it to suit your requirements.
Like #Sunil_D. suggested, listening the mousewheel event and manually adjusting the HorizontalScrollPosition is an easy way to handle this. Add the EventListener for your component
chartList.addEventListener(MouseEvent.MOUSE_WHEEL, chartList_mouseWheelHandler);
and increase/decrease the horizontalScrollPosition with, for example, multiples of event.delta
protected function chartList_mouseWheelHandler(event:MouseEvent):void
{
chartList.verticalScrollPosition -= (event.delta * SOME_CORRECT_VALUE);
}
Finding the proper SOME_CORRECT_VALUE might need some experimenting, but it shouldn't be to hard to find.

How to prevent truncating the bottom of text in Flex comboboxes?

I am currently modifying a flex GUI to give it a new look. I am new to flex but I manage to get most of the work done. However I have a problem with comboboxes: I use a rather big font size and the bottom of some characters is truncated ("g" for example, or any character going under the baseline):
I first thought it was a problem with the component height, but even with a very large height the characters got truncated, with big empty spaces above and under the text.
I looked for a solution on the net but did not find one. Worst: I was not able to find references to my problem though it seems to be an important one. Is there a CSS property to prevent this behavior or do I have to look elsewhere?
edit: I use Flex 3 and Halo/MX components
The combobox component contains an inner TextInput. You have to extend the ComboBox class and modify the height of the textinput to what you need.
For example, lets say you put a font size of 20 and this extended class:
public class MyCb extends ComboBox
{
public function MyCb()
{
addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
private function onCreationComplete(e:Event):void {
this.textInput.height = 40;
}
}
Main application:
<mx:VBox width="100%" height="100%">
<mx:ComboBox fontSize="20" >
<mx:dataProvider>
<mx:Object label="goubigoulba"/>
<mx:Object label="goubigoulba"/>
</mx:dataProvider>
</mx:ComboBox>
<local:MyCb fontSize="20" >
<local:dataProvider>
<mx:Object label="goubigoulba"/>
<mx:Object label="goubigoulba"/>
</local:dataProvider>
</local:MyCb>
</mx:VBox>
You will get the following result:
I believe that this is not the Comobox itself, but its internal label. You can try setting paddingBottom, to see if the label will inherit that, but you might have better luck creating your own subClass of label and using it as the textFieldClass.

Flex image mouse over

I have the next code that show a image and when mouse is over change it.
<mx:Image source="{ConfigApp.getResourcesPath()}/img.jpg" id="imgOne"
mouseOver="imgOne.source=ConfigApp.getResourcesPath()+'/img_over.jpg'"
mouseOut="imgOne.source=ConfigApp.getResourcesPath()+'/img.jpg'"/>
I have 2 problems:
1st: If I pass fast with the mouse over the image, some times the image state with mouseOver image (don't detect the mouseOut event).
2nd: In the moment that mouse is over there are a few miliseconds when the aren't any image, so its looks like a white flash every time that mouse is over.
2nd issue:
Its loading the image each time, this flash will get worse when on a remote connection. instead, cahce the image in a class and switch the class reference.
[Embed(source="/assets/imageOver.png")]
public static const overImage:Class;
[Embed(source="/assets/img.png")]
public static const image:Class;
Then switch them like this...
<mx:Image source="{image}" id="imgOne"
mouseOver="imgOne.source=overImage"
mouseOut="imgOne.source=image"/>
I'd rather make something like this, it solves all the problems:
[Bindable] public var isOurMouse:Boolean = false;
<mx:Canvas>
<mx:Image source="{ConfigApp.getResourcesPath()}/img.jpg"
mouseOver="isOurMouse = true"
mouseOut="isOurMouse = false"/>
<mx:Image source="{ConfigApp.getResourcesPath()}/img_over.jpg"
mouseEnabled="false" mouseChildren="false"
visible="{isOurMouse}"/>
</mx:Canvas>
To the point, if you want your image not to blick on reload, you should have two images, one on another, where background one reloads only after the foreground one has completed loading. Actually, your image blicks, but you don't see it:
<mx:Canvas>
<mx:Image id="imgBkg"/>
<mx:Image id="imgFrg"
source="{something}"
complete="imgBkg.source = imgFrg.source"/>
</mx:Canvas>

width of spark label

I need to set the text of a spark label and then position such label along the x axis depending on its width. Unfortunately, it seems that the width of the label does not update right away and thus the positioning will fail. I can listen to updateComplete events on the label and update its position then, but that means repositioning the label a lot more often than I would like (updateComplete fires off a lot more often than upon changing width). Any ideas on how to properly handle what would appear to be a trivial task?
Here's a code snippet that shows what I described above. If you press the button you will see 3 traces: the label width before changing its text, right after setting its text, and when the label is done updating itself. Would love to know if there's a way to get the correct width without having to listen to updateComplete events... The button and the VGroups are just there to run the example
<?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:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function button1_clickHandler(event:MouseEvent):void
{
trace("label width = ", lb.width);
lb.addEventListener(FlexEvent.UPDATE_COMPLETE, lb_updateCompleteHandler);
lb.text = "hello world!";
trace("label width post change= ", lb.width);
}
protected function lb_updateCompleteHandler(event:FlexEvent):void
{
lb.removeEventListener(FlexEvent.UPDATE_COMPLETE, lb_updateCompleteHandler);
trace("label width post update complete = ", lb.width);
}
]]>
</fx:Script>
<s:VGroup>
<s:Button label="go" click="button1_clickHandler(event)"/>
<s:Label id="lb" text="h" x="10" y="10" />
</s:VGroup>
</s:Application>
The following worked for me. Simple yet works.
var l:Label = new Label();
l.text = "That'll do";
var tlm:TextLineMetrics = l.measureText( l.text);
Alert.show( tlm.width + " is what you are looking for");
VGroup is a Group with VerticalLayout. It doesn't allow to have custom positioning inside group (with x and y). To have this possibility use Group with (default) BasicLayout.
If you use a callLater(), you can "capture" variables in the current scope, but also have it execute after the change in the width has been propagated. For example:
callLater(function():void
{
trace("label width in callLater = ", lb.width);
});
UPDATE: I think I should elaborate a little more to make clear what I meant by "capturing" values. This can be done with the following simple illustration:
callLater(function(prevWidth:Number):void
{
trace("previous label width in callLater = ", prevWidth); // 8
trace("label width in callLater = ", lb.width); // 64
}, [lb.width]);
As the example demonstrates, the parameters that you pass in through the args Array (, i.e., the [lb.width] which becomes prevWidth) take the current value (ie., they pass by value), whereas, the variables you make direct reference to in the function are actually in the scope when the function gets executed (ie., a closure).
You could do this with the event listener also, but with the callLater() it's a little simpler.
looks like listening to resize events does the trick and is not quite as general as updateComplete events, so I'm calling that the "correct answer". There may be a better way to do this when you're trying to position stuff by hand due to performance optimization, although I'm not sure what it is yet.
You can call lb.validateNow() after setting text, this way you will get new width right away. But suggest you to read about components lifecycle not to have such trivial questions.
And yes, as people pointed out already, no repositioning will work with such layout.

Scrolling an editable spark TextArea from Flex Hero Mobile on a touch device

I am having a hard time figuring this out...
How do you scroll an editable TextArea (Flex Hero) on a touch device?
I am referring to the situation where the text does not fit in the TextArea height.
When I try to tap and drag the text gets selected and not scrolled... Am I missing a something here? I am using verticalScrollPolicy = on (also tried auto).
I am testing the code in the Blackberry Playbook simulator (my targeted device for my app).
If you have any hints or suggestions please let me know.
Thanks,
A TextArea is an editable component. You should try using RichText instead if you don't want to edit the text.
Put it in a s:Scroller:
<s:Scroller id="prayerSc" width="100%" height="100%">
<s:RichEditableText id="prayerText" width="100%" height="100%" clipAndEnableScrolling="true" selectable="true" editable="true" textFlow="{PTFL}" />
</s:Scroller>
RichEditableText is not optimized for mobile
Use this instead Orig source
import spark.components.supportClasses.MobileTextField;
private var cnt:int = 0;
protected function addText():void
{
ta.appendText('More text... ' + cnt++ + '\n');
MobileTextField(ta.textDisplay).scrollV++;
}
<s:TextArea id="ta" width="95%" height="200" editable="false"/>

Resources