views:

4281

answers:

4

I'm developing an application with Adobe Flex and AIR, and I've been banging my head against the wall trying to figure out how to solve a scrolling issue.

The basic structure of my main application window (simplified greatly) is this:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
   paddingTop="0" paddingRight="0" paddingBottom="0" paddingLeft="0"
   width="800" height="600" layout="vertical" verticalAlign="top" 
>
   <mx:VBox id="MainContainer" width="100%" height="100%">
      <mx:Panel id="Toolbars" width="100%" height="25" />
      <mx:HDividedBox width="100%" height="100%" >
         <mx:Panel id="Navigation" minWidth="200" height="100%" />
         <mx:VBox id="MainContent" width="100%">
            <mx:Panel width="100%" height="200" />
            <mx:Panel width="100%" height="200" />
            <mx:Panel width="100%" height="200" />
            <mx:Panel width="100%" height="200" />
            <mx:Panel width="100%" height="200" />
         </mx:VBox>
         <mx:Panel id="HelpContent" minWidth="200" height="100%" />
      </mx:HDividedBox>
      <mx:Panel id="FooterContent" width="100%" height="25" />
   </mx:VBox>
</mx:WindowedApplication>

The trouble is that the "MainContent" box might contain a huge list of subcomponents, and the presence of that long list causes a vertical scrollbar to appear at the highest level of the GUI, surrounding the "MainContainer" vbox.

It looks really silly, having scrollbars around the entire application window.

What I'm looking for instead is a solution where the scrollbar is only applied to the "MainContent" vbox (as well as the Navigation and HelpContent panels, if their content stretches past the window bounds).

I found a related question on StackOverflow, where the problem's solution was to use "autoLayout" and "verticalScrollPolicy" attributes on parent containers.

So I tried adding autoLayout="false" and verticalScrollPolicy="off" attributes to all of the parent containers, as well as verticalScrollPolicy="on" to the "MainContent" vbox. But the end-result of that experiment was that the content was simply clipped from the main container (and a useless scrollbar with no thumb was added to the MainContent vbox).

Anyone know how to solve this?

+1  A: 

Found a solution.

Looks like the only way to prevent the VBox from aggressively extending its vertical space (and forcing its parents to grow scrollbars) is to wrap the VBox in a Canvas.

There's a handy little component here, called ScrollableVBox, which performs the workaround while taking care of a few bookkeping issues (like adding and removing children to the VBox, passing them around the Cavas wrapper).

benjismith
A: 

Your problem seems like a lot like one that I struggled with some time ago. I found my answer from this discussion: just disable the measure() implementation of the Box.

This was a pretty easy fix which worked perfectly in my case and hasn't caused any "collateral damage". Your results may vary.

package whatever
{
    import mx.containers.Box;

    /**
    * A Box that has no measure() implementation.
    * 
    * <p>
    * See <a href="http://tinyurl.com/2hvmav"&gt;here&lt;/a&gt; for more info.
    * </p>
    */
    public class NonMeasuredBox extends Box
    {
        /**
        * Constructor
        */
        public function NonMeasuredBox():void
        {
            super();
        }

        override protected function measure():void { /* disabled */ }
    }
}
hasseg
I'll give that a try later in the afternoon. I'd imagine, though, that disabling measure makes it difficult to provide horizontal resizing of the container. I just want to fix the vertical scrolling problem.
benjismith
You're totally right -- this is a pretty drastic hack but might be useful in some specific situations (like mine.)
hasseg
+4  A: 

An HBox or a VBox will try as hard as possible to display its content without scroll bars. This forces a parent container (often all the way up to the main Application) to be the one that must scroll if the content is too large to fit in the available bounds.

Behind the scenes, the HBox or VBox is setting the measuredMinWidth and measuredMinHeight properties in its measure() function to match the dimensions required by its children. The parent container will honor that recommendation and the task of scrolling moves up the display list.

hasseg's solution works in many cases because it stops the container from measuring, but it's kind of hacky. Here's what you can do without building replacement subclasses for your containers. On the container instance that you want to scroll, set minWidth or minHeight to 0. This will take precedence over the measuredMinWidth or measuredMinHeight properties of that container, allowing the parent to set the actual size to something more manageable.

joshtynjala
A: 

It seems like giving fixed height or width in pixels (and not percentage!) to a given box will solve the problem without addition Canvas enclosure. However this only works if you know the size of the box in pixels, dynamic sized boxes still lack the ability of rendering properly.

ifroz