20 Replies Latest reply on Dec 18, 2009 10:38 AM by ngarg

    TileLayout spark Item Renderer and Zoom in and zoom out

    ngarg Level 1

      I implemented a spark ItemRenderer, which serves a DataGroup with TileLayout:

       

          <s:Border id="scrollView"
                    styleName="scrollView"
                    width="100%"
                    height="100%">

       

              <s:filters>
                  <s:DropShadowFilter inner="true"
                                      alpha=".35"/>
              </s:filters>

       

              <s:Scroller id="continuousViewScroller"
                          height="100%"
                          width="100%">

       

                  <s:DataGroup id="continuousView"
                               height="100%"
                               width="100%"
                               itemRenderer="PageRenderer"
                               dataProvider="{pages}">

       

                      <s:layout>
                         
                               <s:TileLayout columnAlign.OneUpView="justifyUsingWidth"
                               columnAlign.TwoUpView="left"
                               verticalGap="10"
                               horizontalGap.TwoUpView="10"
                               horizontalAlign="center"
                               verticalAlign="top"
                               useVirtualLayout="true"
                               clipAndEnableScrolling="false"
                               requestedColumnCount.OneUpView="1"
                               requestedColumnCount.TwoUpView="2"/>
                         
                         
                          <!--
                          <s:VerticalLayout horizontalAlign="center"
                                            useVirtualLayout="true"
                                            clipAndEnableScrolling="false"
                                            variableRowHeight="true"
                                            paddingTop="5"
                                            paddingBottom="5"
                                            requestedRowCount="2"/>
                          -->
                      </s:layout>
                  </s:DataGroup>
              </s:Scroller>
          </s:Border>

       

      I execute a zoom effect everytime some one pushes zoom in or zoom out buttons. The trouble is that zoom in and zoom out works fine. However, the gap between two item renderers increase, when I zoom out.

       

      Is there a way that the gap remains fixed?

        • 1. Re: TileLayout spark Item Renderer and Zoom in and zoom out
          Shongrunden Adobe Employee

          Is it the verticalGap or the horizontalGap that changes?

           

          I haven't looked at this very closely, but I assume you "zoom in" by going into the TwoUpView state.  Notice that you set the horizontalGap to be different in that state:

           

          <s:TileLayout
              ...
              horizontalGap.TwoUpView="10"
              ... />
             
          The horizontalGap will be 6 (by default) in all other states and then 10 in the TwoUpView state.  Is this the problem you are seeing?

           

          If so you can make the horizontalGap consistent between the two states with something like this:

           

          <s:TileLayout
              ...
              horizontalGap="10"
              horizontalGap.TwoUpView="10"
              ... />

           

          or just simply:

           

          <s:TileLayout
              ...
              horizontalGap="10"
              ... />

          • 2. Re: TileLayout spark Item Renderer and Zoom in and zoom out
            ngarg Level 1

            Zoom in means, within the PageRenderer, I use a Scale effect, which zooms in and out based on an event. The following code is for doing zoom in and zoom out for the PageRenderer. It works fine. However, the vertical/horizontal gaps increases once have a zoomed in and then try to zoom out incrementally. I want to keep the gap between elements same all the time.

             

            If I run this same code, with VerticalLayout, It works great. However, this does not work with TileLayout.

            The following link:

             

            http://opensource.adobe.com/wiki/display/flexsdk/Spark+TileLayout

             

            says:

             

            "Note that justify only grows the columnWidth/rowHeight, so to handle cases where the size of the columns/rows has to shrink, the default column width/row height should set explicitly to zero."

             

            Does anyone has any idea how to implement this?

             

            Source Code for zoom in and zoom out:

             

            <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/halo"
                            creationComplete="init()">

             

                <fx:Declarations>
                    <s:Scale target="{this}" id="zoomPlayer"  duration="150" />
                </fx:Declarations>

             

                <fx:Script>
                    <![CDATA[
                      
                        import mx.core.FlexGlobals;
                        import mx.events.EffectEvent;
                       
                        private var _zoom:Number=1.0;

                        [Bindable]
                        public function set zoom(value:Number):void
                        {
                            _zoom=value;
                        }

             

                        public function get zoom():Number
                        {
                            return _zoom;
                        }

             


                        private function init():void
                        {
                            var proj:TestProject=FlexGlobals.topLevelApplication as   TestProject;
                            proj.systemManager.addEventListener(ZoomEvent.ZoomChange, updateZoom);
                        }

             

             

                        private function updateZoom(event:ZoomEvent):void
                        {
                            if(zoom != event.zoom){   
                                if(zoomPlayer.isPlaying){
                                    zoomPlayer.stop();
                                }
                                zoomPlayer.addEventListener(EffectEvent.EFFECT_END, zoomEnd);
                               
                                zoomPlayer.scaleXFrom=zoom;
                                zoomPlayer.scaleXTo=event.zoom;
                                zoomPlayer.scaleYFrom=zoom;
                                zoomPlayer.scaleYTo=event.zoom;
                                zoomPlayer.play();
                               
                                zoom=event.zoom;
                            }
                        }

             

                        private function zoomEnd(event:EffectEvent):void{
                            zoomPlayer.removeEventListener(EffectEvent.EFFECT_END,zoomEnd);
                        }

            }

            • 3. Re: TileLayout spark Item Renderer and Zoom in and zoom out
              Shongrunden Adobe Employee

              I think I might know what is going on.  In TileLayout each element is laid out inside a "cell" and each cell is of equal size: the largest renderer in the List.  When you grow one of your renderers the layout responds and increases the size of every other cell.  Depending on how your renderer is set up that might visually result in larger gaps.

               

              I think what you want is to scale the renderer in a way that the layout doesn't respond to.  You can do this with the postLayoutTransformOffsets property.

               

              Take a look at an example here:

              http://flexponential.com/2009/06/24/zoom-in-on-items-in-a-list-with-a-tilelayout/

               

              Does that help?

              • 4. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                ngarg Level 1

                Nope. I am facing the same issue.

                 

                Funny thing is that if I change the layout to VerticalLayout and enable variableHeight=true. My code works beautifully.

                 

                Essentially, I need to simulate a one-up view and a two-up view. TileLayout gives me a nice way to control this with states.

                 

                I can toggle  oneUp.requestedColumnCount=1, twoUp.requestedColumnCount=2. With vertical, I will have to come up with a different solution.

                • 5. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                  ngarg Level 1

                  Nope. It does not work. The only way I could get the zoom to work correctly is when I change the layout to VerticalLayout and set the variableHeight=true.

                   

                  However, I need to simulate a one-up and two-up views. I can achieve that using TileLayout by simply creating two states "oneUp" and "twoUp" and then assign requestedColumnCount="oneUp" and requestColumnCount="twoUp".

                   

                  Is there a way to create nested layouts. Something like a HorizontalLayout inside a vertical layout?

                  • 6. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                    Shongrunden Adobe Employee

                    Looks like I'm not understanding what is going on.  Any chance you could post a ZIP of your application code (or a trimmed down version of it) that demonstrates the issue?

                    • 7. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                      ngarg Level 1

                      Here you go!

                       

                      This is an Eclipse project and I am currently using Flash Builder 4 Beta 2.

                       

                      a) You will have to add some images (PNG files) in bin-debug/data directory.

                       

                      b) Rename the images to image_0001.png, image_0002.png ... image_nnnn.png

                       

                      c) Finally,  update the NUM_OF_IMAGES property in TestProject.mxml

                       

                      d) If you wish to use any other type of image, simply change the extension in createItems() method.

                      • 8. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                        Shongrunden Adobe Employee

                        Ah I think I see what you are doing now.  It looks like the issue is related to virtual layout.

                         

                        If you set useVirtualLayout="false" on the TileLayout I believe you will get the behavior you are expecting.

                         

                        Does that work for you?

                         

                        This is happening because of a current limitation in TileLayout virtualization that the "cell" size will increase if an item in view gets bigger, but it will never decrease when items get smaller.

                         

                        Note: Locally I changed the s:Border to a mx:Canvas in your ItemRenderer just to be safe because I wasn't sure if spark containers play nicely when drawing into their graphics object.

                        • 9. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                          ngarg Level 1

                          Setting useVirtualLayout=false does not work.  I am still getting the same problem. Were you able to run the application at your end?

                           

                           

                          Virtual layout gives me performance advantage. Without this, you can cache Image binaries at client side and BitmapData objects for large images will eat a lot of Heap Space. For loading 181 image where each image is 700 X 1000, without virtual layout, it takes 800 MB. With virtual layout it takes around 400 MB.

                           

                          Also, s:Border works just fine.

                          • 10. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                            Shongrunden Adobe Employee

                            Weird - it seems to work fine for me.  I'm on 4.0.0.11912.  The images don't seem to load for me unless I switch out s:Border for mx:Canvas.  (I dont know anything about the graphics object just tried going to Canvas on a random hunch.

                             

                            I've attached a ZIP with the changes I made:

                            - added 9 images

                            - set number of images to 9

                            - set useVirtualLayout=false

                            - change s:Border to mx:Canvas

                             

                            Does this ZIP work for you, or (more likely) am I missing something again?

                            • 11. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                              Shongrunden Adobe Employee

                              I spent a little time hacking away at a workaround for your particular case.  See attached.  This should allow you to resize your elements larger and smaller without needing to turn off virtual layout.

                               

                              I setup an effect on the main Application, let the renderers bind their scaleX/scaleY to a bindable scaleFactor property on the Application, and as I animate scaleFactor I also animate the columnWidth/rowHeight properties of the TileLayout to keep it in sync.

                               

                              Caution: This code sample is a workaround for a limitation in virtual TileLayout.  This is one way of doing this, but I dont know if it's the best way or if it's even correct/complete, so take it with a grain of salt.  Hopefully it helps.

                              • 12. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                ngarg Level 1

                                Nope. This is not helpful either.

                                • 13. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                  mewk Level 3

                                  worth mentioning:

                                  1. the behavior of this project is heavily dependent on build. the images are rendering fine with the stable build, but require modification for later nightly builds (this whole business of canvas vs border, etc.).
                                  2. i think the problem is the tile layout -- don't use it. the documentation for tile layout reads as follows: "All cells of the tile layout have the same size, which is the height of the tallest child and the width of the widest child." So what happens? well a) you get inconsistent gaps between the images and b) when you zoom in on an image the property that determines the "tallest child" increases and stays stuck so when you zoom back out the tile layout keeps at the maximum item height it remembers.

                                   

                                  best o luck,

                                   

                                  - e

                                  • 14. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                    Shongrunden Adobe Employee

                                    Regarding drawing into the graphics property of a spark Border component:

                                     

                                    I talked with the developer of the Border component about this approach and this was his response:

                                     

                                    "Doing this is not officially supported. It is possible to do and should work. However, if your intention is to draw on the inside of the border, then it is probably better to put a container inside of the Border and draw into that instead. That way if the border weight changes size, you'll still draw inside of the border. Another issue is that anything you draw will be below the border and fill of the skin."

                                     

                                    This is working in older builds, but failing in newer builds because the image is being drawn behind a white background (which is a bug: the background should be transparent by default, see http://bugs.adobe.com/jira/browse/SDK-24073).

                                     

                                    Instead of drawing into a Border you should consider drawing into an Image component wrapped in a Border:

                                     

                                    private function drawImage():void
                                    {
                                        var myBitmap:Bitmap = new Bitmap(_bitmapData);
                                        canvas.source = myBitmap;
                                        ...
                                    }
                                    ...
                                    <s:Border borderColor="0xC0C0C0" width="100%" height="100%">
                                        <mx:Image id="canvas" width="100%" height="100%" />
                                    </s:Border>
                                    • 15. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                      Shongrunden Adobe Employee

                                      @mewk - You're right that the cell size is non-decreasing, but that is only in the virtual case.  It should work fine with useVirtualLayout="false".  The workaround I posted in the virtual case is to keep the columnWidth/rowHeight properties of the layout in sync as item sizes change.  The sample I posted is very simple and naive and should work for the specific input I provided, but will likely break down if you have different sized items.  Being smarter about what to set columnWidth/rowHeight to should help tho.

                                       

                                      @ngarg - If you launch the workaround I provided does that not work for you, or does applying that approach to your original project not work?

                                      • 16. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                        ngarg Level 1

                                        Thanks!

                                         

                                        I did a prototype for a custom layout today based on what I read in this article (http://www.adobe.com/devnet/flex/articles/spark_layouts_04.html). I am planning to do a concrete implementation over the next few days for doing "one up view" and a "two up view". While building this prototype, I realized that implementing Spark Virtualization is going to be tricky, which is absolutely critical for my application.

                                         

                                        Any thoughts?

                                        • 17. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                          Shongrunden Adobe Employee

                                          Sounds good - let us know how it goes.

                                           

                                          To get started you will probably want to read the spark virtualization spec here: http://opensource.adobe.com/wiki/display/flexsdk/Spark+Virtualization

                                          • 18. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                            ngarg Level 1

                                            Here is my attempt to do a custom layout, which can do the following things:

                                             

                                            1) One up View (Similar to vertical layout)

                                            2) Two up View (two elements side-by-side)

                                            3) Adjust zoom (Needs optimization)

                                            4) Scrolling (It is fast!)

                                            5) Supports virtualization ( Memory efficient! You can use this layout scheme to display a large number of elements.)

                                             

                                            The basic assumption of this layout is that element height and width are approximately the same for all the layout elements, which works beautifully in my case.

                                             

                                            I need to straighten out code to make the following work more smoothly:

                                             

                                            1) Switch views from "One Up" to "Two Up" view, should keep the current item view in place. So if i am in the middle of 45th item, two up view should

                                            should me the exact item at approximately the same position.

                                            2) Adjust layout elements in view whenever you update zoom. Right it s a bit jerky. Also, the current view should zoom in or out in place, without scrolling the pages up or down.

                                            3) In the updateDisplayList method, if I do the calculations right, I am be able to remove the loop. I need to think about this little more.

                                             

                                            Here is how i am using this attached CustomVerticalLayout layout:

                                             

                                                    <s:Scroller id="viewerScroller"
                                                                height="100%"
                                                                width="100%">

                                             

                                                        <s:DataGroup id="viewerDataGroup"
                                                                     height="100%"
                                                                     width="100%"
                                                                     itemRenderer="CustomItemRenderer"
                                                                     dataProvider="{itemList}">
                                                            <s:layout>

                                             

                                                            <components:CustomVerticalLayout gap="10"
                                                                                       layoutType.TwoUpView="twoUpView"
                                                                                       layoutType.OneUpView="oneUpView"
                                                                                       zoom="{zoom}"
                                                                                       elementWidth="{typicalElWidth}"
                                                                                       elementHeight="{typicalElHeight}"
                                                                                       useVirtualLayout="true"
                                                                                       clipAndEnableScrolling="true"  />
                                                            </s:layout>
                                                        </s:DataGroup>
                                                    </s:Scroller>

                                            • 19. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                              Shongrunden Adobe Employee

                                              Glad to hear you got it working.  I tried using your layout but got a bunch of compiler errors.  If you have a spare minute some time it would be great if you could post a small sample app that works with it.

                                              • 20. Re: TileLayout spark Item Renderer and Zoom in and zoom out
                                                ngarg Level 1

                                                Here you go!

                                                 

                                                This is a crude example of what I am trying to implement. I will be very glad if you can suggest any optimizations. Especially, reducing memory footprint, if possible, with larger datasets.