views:

1559

answers:

6

I have set the itemRollOver and itemRollOut event listeners on a List component, but whenever I roll the mouse over a list item, both the over and out events of the same list item fire in succession right after each other. My list uses a custom itemRenderer.

Any ideas why this might be? The Adobe documentation doesn't provide much insight into this (not surprisingly...).

A: 

Are they coming from the same object? If not you will it is likely so that you will get an itemRollOut from the "item" you just left and a itemRollOver from the new one you entered, depending on their spacing and such these may fire very close to each other.

grapefrukt
The events are fired by the same object. The objects are not overlapping, they are right next to each other (0 pixels in between).
Niko Nyman
A: 

Make sure you are setting super.data in your item renderer if you are overriding set data().

ListBase listens for MOUSE_OVER and then figures out the item underneath it based on coordinates of mouse and the position of the item renderer. You could check ListEvent.itemRenderer to see which renderer's roll over and roll out are firing and in what order.

Worst case, you could listen for rollOver and rollOut inside your item renderer.

anirudhsasikumar
+1  A: 

In my opinion this is a bug. The ListBase.mouseOverHandler now sets a variable called lastHighlightItemRendererAtIndices when it dispatches an ITEM_ROLL_OVER event, which is then used (together with lastHighlightItemIndices) when dispatching an ITEM_ROLL_OUT event in ListBase.clearHighlight (called by the mouseOutHandler).

The problem is that when you mouse from row-to-row the mouseOverHandler is called first, setting the lastHightlight... variables, and then when the mouseOutHandler gets called subsequently, it uses the lastHighlight... values that were just set with the result that you get consecutive 'roll over' and 'roll out' events for the same renderer.

Frankly I don't know why ListBase.clearHighlight just doesn't use the passed in renderer when dispatching the ITEM_ROLL_OUT event (which is how it used to work in SDK 2) as this is the actual renderer that is being 'rolled out of'.

Interesting, and would explain the behaviour. Can anyone confirm this? (Unfortunately I don't have time to dig in the mx code right now.)
Niko Nyman
A: 

Had the same problem. super.data was already being set, and the item is the same for the rollOut and rollOver event. I ended up opting for anirudhsasikumar's worst case scenario, and listened for rollOver and rollOut inside the item renderer. Seems to work fine.

A: 

I was having this same issue. I ended up subclassing the mx.controls.List class and overriding the clearHighlight function. As far as I can tell, the lastHighlightItemIndices variable is only ever read in that function. So doing something like the following fixed this issue:

import mx.core.mx_internal;

use namespace mx_internal;

public class List extends mx.controls.List
{
    public function List()
    {
        super();
    }

    override mx_internal function clearHighlight( item:IListItemRenderer ):void
    {
        var uid:String = itemToUID( item.data );

        drawItem( UIDToItemRenderer( uid ), isItemSelected( item.data ), false, uid == caretUID );

        var pt:Point = itemRendererToIndices( item );

        if( pt )
        {
            var listEvent:ListEvent = new ListEvent( ListEvent.ITEM_ROLL_OUT );

            listEvent.columnIndex = item.x;
            listEvent.rowIndex = item.y;
            listEvent.itemRenderer = item;

            dispatchEvent( listEvent );
        }
    }
}

Then just use this List class instead of the Adobe one and you'll have the behavior you expect. I tested this against Flex SDK 3.2 and it works.

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:controls="com.example.controls.*">

    [ other code ... ]

    <controls:List itemRollOver="onItemRollOver( event )" itemRollOut="onItemRollOut( event )" />

</mx:Canvas>

Thanks to Gino Basso for the idea in the post above. Hope that helps.

RJ Regenold
Thanks for the tip. I will try it out when I return to the project in question!
Niko Nyman
A: 

Hi

thanks for the solution. that really solved the problem!

small correction, though

listEvent.columnIndex = item.x;
listEvent.rowIndex = item.y;

should be

listEvent.columnIndex = pt.x;
listEvent.rowIndex = pt.y;

item.x and y hold the coordinate of the renderer in pixels

sofajazz