Zoom in on items in a List with a TileLayout

This sample demonstrates one way of modifying the postLayoutTransformOffsets property of an ItemRenderer in a List in order to have the items appear to zoom in when hovered or selected.

The depth and postLayoutTransformOffsets properties of UIComponent can be very useful when you want to make changes to an element in a Group without causing the Group’s layout to reposition all of the elements. For example if you have a VerticalLayout on a Group of elements and then change scaleY on the first element, the layout will appropriately move all of the other items down to make room for the new size of the first element. Sometimes this behavior isn’t ideal and that’s where the postLayoutTransformOffsets property comes in. Any changes you make to a component’s postLayoutTransformOffsets property is done without the layout aware of anything going on. Below is a sample application that demonstrates one case of this. We want the items of a List to grow larger when we hover over them, but we don’t want the other items to get moved around by the layout.

Here is the sample application:

View Source

If you look at the code for the ItemRenderer you will see that it defines a default depth value of zero and then defines a higher depth value for the hovered and selected states. This will cause that particular item renderer to be shown on top of everything else which has a lower depth.

Now with the renderer “popped out” in front of the other items we can change the size and position of the renderer to create a sort of zooming in effect when someone hovers over or selects an item.

The List in this sample uses a TileLayout with useVirtualLayout enabled in order to be able to handle large collections of data. I intend on posting more information about virtualization to this blog in the future. In the mean time you can read all about it in the Spark Virtualization Spec.

Note: This sample requires Flex SDK 4.0.0.10957 or higher. You can get the latest SDK builds from opensource.adobe.com.

13 thoughts on “Zoom in on items in a List with a TileLayout”

  1. Great post! How would you go about moving all the hovered objects to the center of the list component? So if I hover over item0 I would like it to move to the center of the list component and do the scale up at that point.

  2. @Jason – If you look at mx.geom.TransformOffsets you will see that you can control rotation, scale, and position in postLayoutTransformOffsets. You could build some logic into your renderer that would set the position to the center of the List but that will get tricky pretty fast and I wouldn’t recommend that approach. Also moving something in the hovered state might not work as you expect since it will no longer be hovered if it moves enough such that it is no longer under the mouse. This will cause a flickering.

  3. Flex is completely new for me (I am right now going through “Learn Flex in a week by video”).
    I used this example to create my own custom component that displays horizontal menu build from icons with some additional effects:
    a. icons are originally small, blurred and greyed (normal state)
    b. icon become zoomed, “unblurred “ and displayed with original colors in hovered state
    c. selected icon returns to small size, but remains to be “unblurred” and color

    The problem is that I would like to have additional state called “disabled” that can be set during component initialization and allow me to display some of the icons in the normal state, but they cannot be selected or hovered.

    I try to use your example from “Disable selection on some items in a spark List” article, but it does not work correctly. When you select any entry on the list and then click on the non-selectable heading, previously selection disappears.

    Any suggestion how to modify your code to create such additional state?

  4. Could you be so kind as to perform a quick regression test of your very helpful example against the most current SDK – 4.1. The mxmlc compiler says that it cannot “resolve (mx:TranformOffsets) to a component implementation”.

    I suspect that something changed from the Beta code you were using with respect to the use of the fx:Component tag, but since you know Gumbo, and I don’t, my guess probably isn’t even close to the real cause of the diagnostic.

    Thank you.

  5. Please just remove my comment/question. The only required change was the URL for the mx namespace from halo to mx.

  6. @Terry Corbet – Thanks for pointing this out. I should probably update this code sample at some point, but in the mean time to use this with Flex 4.0/4.1 release builds you will need to update the mx namespace from:

    xmlns:mx=”library://ns.adobe.com/flex/halo”

    to:

    xmlns:mx=”library://ns.adobe.com/flex/mx”

  7. Thanks for following up. As I said in my second posting, the change was so insignificant that I had hoped you would just delete my comments. But, since you did not, and since my ignorance is exposed, let’s see if I can make it worse.

    I have continued to work your sample code, but I cannot entirely eliminate the ‘flicker problem’ which you correctly pointed out could be a problem under some conditions. Most readers will have also found the very similar Chris Coenraets example, http://coenraets.org/blog/2010/02/more-flex-4-spark-itemrenderer-samples/, including the caveat from Ely Greenfield, concerning the need for ‘protective coding’ in the form of a ‘hitArea’.

    I wish I could post a screenshot of my implementation to demonstrate my ‘flickering problem’. At least I ought to mention what I think might be slight differences that could impact on my problem: First, mine is an AIR application; when testing via adl, the flickering problem is greatly exacerbated. Second, my grid of tiles is 50×50 versus your 100×60, with correspondingly smaller gaps.

    So, even with the addition of hotspot detection which DOES NOT participate in the zoom animation, it is entirely possible for the user to get flickering based on some mouse gesture. You obviously encountered and seemingly overcame the problem — I have never been able to induce flickering in our web-based demo — without following the Greenfield recommendation [as, by the way, neither did Coenraets].

    Can you provide any advice concerning what geometry and/or events and/or any other characteristic of the application must be obeyed to insure that the user will never see flickering?

  8. @Terry Corbet – I didn’t think your comment was insignificant at all, in fact I was glad you brought it up because the original code sample was from a very early build of Flex 4 before it was released. Most people wouldn’t know that the namespace changed unless they were following the progress of the SDK before it was released. I figured your comment would be useful to others and so I left it up.

    I tried playing around with this example to induce flickering, but I haven’t been able to. It’s interesting that you are seeing different behavior in AIR versus in the browser. If you have a sample Flash Builder project that demonstrates the issue I would be happy to take a look at it to try and figure out what is going on (steve at flexponential).

  9. This may be a newbie question – I love this example, was able to get it working right away. Is there any way that when the item is rolled over the zoom effect would actually push the other list items around? Similar to what is seen here where instead of overlapping the adjacent items on rollover it moves them: http://demo.quietlyscheming.com/fisheye/TileExplorer.html

    Not sure if that is possible or not… Thanks in advance for any input!

  10. @Julia – The spark TileLayout lays out all of its elements in equal sized “cells” so if one element grows larger causing an increase in cell size then every cell in the layout will increase. You can see this behavior by applying the effects to the ItemRenderer itself rather than the ItemRenderer’s postLayoutTransformOffsets property. Also when TileLayout is using virtual layout cell size can grow, but will not reduce size back down. You’ll see that Ely’s example has a different cell size for the column and row currently hovered over. I don’t think you will be able to get that behavior with the stock spark TileLayout, but you should be able to create a custom layout that does support that.

Comments are closed.