Controlling which VBox gets the scrollbar - apache-flex

I have the following application and I am trying to put a scrollbar somewhere inside the TabNavigator, preferably on the innermost Vbox, but the scrollbar always ends up on the Panel. Is there some kind of property which controls this? I thought height=100% would have controlled it but it doesn't seem to work.
Sample is here. You can view source on it:
VBox Sample
Here is the source anyway:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" viewSourceURL="srcview/index.html">
<mx:Panel width="400" height="400">
<mx:TabNavigator width="100%" height="100%" creationPolicy="all">
<mx:VBox label="Tab 1" width="100%" height="100%">
<mx:ViewStack width="100%" height="100%">
<mx:VBox width="100%" height="100%">
<mx:Text width="100%" height="500" text="This box is taller than the Panel, but the scrollbar is on the window." />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:TabNavigator>
</mx:Panel>
</mx:Application>

I found the proper solution is to set the minheight on the box to 0. When the minheight is not defined, the box will try to remain at it's measured height. By setting the minheight you are telling the box it is ok to shrink.

I've had this issue in the past, and the solution is a bit wonky, but hopefully this helps:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Panel width="400" height="400" verticalScrollPolicy="off">
<mx:TabNavigator width="100%" height="100%">
<mx:VBox id="container" label="Tab 1" width="100%" height="100%">
<mx:ViewStack width="100%" height="{container.height - 20}">
<mx:VBox width="100%" height="100%">
<mx:Text width="100%" height="500" text="This box is taller than the Panel, but the scrollbar is on the window." />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:TabNavigator>
</mx:Panel>
</mx:Application>
Flex seems to calculate dynamic component dimensions properly about 98% of the time, but sometimes we need to "massage" the logic.
When you look at your layout hierarchy (as I've shown above), you just need to name the parent container (in this case Tab1) for the purposes of data binding, then use that container's height property for your sizing. (you also don't need to explicitly state verticalScrollPolicy="off" on the panel, but I use if for good measure :P)
Note that you may need to subtract a bit from the given height or your scrollbar will be below the component bounds ;)

Related

In flex, how to declare a control to take all available width

In Flex 4.0, I have a project with a videodisplay, and below it some controls that I've created (play/pause button, HSlider for showing progress, some volume controls...)
The problem arises when the flash is displayed in a window that is too small to fit all controls at their desired width. What I see is that some controls are pushed to the right, out of sight. (Maybe it's because they are in a custom container that acts as a window, but that's needed functionality).
I want to designate the HSlider as having flexible width, so when the user creates a small window, the items in the control bar are still visible, and the HSlider is compressed enough to make that happen...
Cheers!
Edit: the code for my window (it's the VBox that I would like to have variable-sized):
<ns1:CollapsableTitleWindow x="294" y="36.65" backgroundColor="#000000" width="436" height="373" id="wnd" title="test" allowClose="false">
<mx:VideoDisplay width="100%" height="100%" id="vd" autoPlay="false" volume="1"/>
<mx:ControlBar id="ctrlbarLiveVideo1" width="100%">
<mx:Button width="30" height="22" id="btnPlay" click="{doplay();}" icon="{imgPlayButton}"/>
<mx:VBox verticalGap="1" horizontalAlign="right">
<mx:HSlider id="slider" width="100%" invertThumbDirection="true" maximum="{vd.totalTime}" minimum="0" tickInterval="{vd.totalTime/10}" value="{Number(vd.playheadTime)}" />
<mx:Label text="{sec2hms(Number(vd.playheadTime))} / {sec2hms(Number(slider.maximum))}"/>
</mx:VBox>
<mx:HBox id="box" horizontalGap="1" verticalAlign="middle">
<mx:Label id="lblVolume" text = "{String(Math.round(vd.volume*100))+'%'}"/>
<mx:Button label="-" id="btnless" width="34" height="22" verticalGap="0" labelPlacement="top" labelVerticalOffset="0" click = "{vd.volume -= 0.10}"/>
<mx:Button label="+" id="btnmore" width="34" height="22" verticalGap="0" labelPlacement="top" labelVerticalOffset="0" click = "{vd.volume += 0.10}"/>
</mx:HBox>
</mx:ControlBar>
</ns1:CollapsableTitleWindow>
Produces this screenshot:
Apparently the answer was: set the minWidth of the HSlider explicitly to 0:
<mx:HSlider minWidth="0" id="slider" width="100%" ... />
And also make the VBox width="100%": (thanks to code90)
<mx:VBox width="100%" verticalGap="1" horizontalAlign="right">

Why do I have a gap within my TabNavigator?

Apologies for the rookie Q - trying to learn Flex/Actionscript and just having some basic layout issues. (Using FlashBuilder 4, with Flex 4.5 HERO SDK)
I have a TitleWindow, and have embedded a mx:TabNavigator within it.
I have then placed a list within the first tab and set its width/height to 100%
However, there appears to be a gap between the top of the list, and the bottom of the tab menus.
Why is this happening and what is the best way to ensure the top of the list aligns up flush with the top of the VBox?
<s:TitleWindow title="Dekho Resource Center"
id="titleWindow"
close="cancel();"
width="375"
height="500"
backgroundAlpha="0"
cornerRadius="5">
<mx:TabNavigator borderStyle="solid" left="0" top="0" width="100%" height="100%" backgroundAlpha="0" >
<mx:VBox label="Blog Posts"
width="100%"
height="100%">
<s:List labelField="title" id="theList" width="100%" height="100%"
contentBackgroundAlpha="0.7" rollOverColor="#F58B57" selectionColor="#FF7227"
doubleClickEnabled="true" doubleClick="theList_doubleClickHandler(event)">
<mx:AsyncListView list="{getDataResult.lastResult}"/>
</s:List>
</mx:VBox>
<mx:VBox label="Search"
width="100%"
height="100%">
</mx:VBox>
</mx:TabNavigator>
Remove the padding from the TabNavigator:
<mx:TabNavigator paddingTop="0"
paddingLeft="0"
paddingRight="0"
paddingBottom="0">

Flex 4 Scroller component doesn't render horizontal scrollbar

I'm pretty sure my dynamic mxml layout must give me two scrollbars (horizontal and vertical) but it only shows vertical one.
Am I missing something or is it a bug?
<?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" width="100%" height="100%" xmlns:local="*">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var myData:ArrayCollection = new ArrayCollection([
{name:"Jane"},
{name:"Sonny"},
{name:"Alicia"}
]);
]]>
</fx:Script>
<s:Scroller width="100%" height="100%">
<s:VGroup>
<s:Group minHeight="600" minWidth="800" height="100%" width="100%">
<mx:HDividedBox id="div1" width="100%" height="100%" autoLayout="true" liveDragging="true">
<mx:DataGrid width="100%" height="100%" dataProvider="{myData}"/>
<mx:DataGrid width="100%" height="100%" dataProvider="{myData}"/>
</mx:HDividedBox>
</s:Group>
</s:VGroup>
</s:Scroller>
</s:Application>
Remove the VGroup inside the Scroller or change it to Group!
Seems that the horizontal scrollbar is not shown when using VGroup as first child
You haven't set horizontalScrollPolicy and verticalScrollPolicy for the Scroller and hence they have their value set to the auto. The behavior in this case is to display the scrollbars only if necessary.
The scroll bars are displayed according to the vertical and horizontal scroll bar policy, which can be auto, on, or off. The auto policy means that the scroll bar will be visible and included in the layout when the viewport's content is larger than the viewport itself.
Try with
<s:Scroller width="100%" height="100%" horizontalScrollPolicy="on">

Flex fixed and variable height - can it be set in markup?

I've got the following Flex application markup:
<app:MyApplicationClass
xmlns:app="*"
width="100%"
height="100%"
layout="vertical"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:VBox id="idPageContainer" width="100%" height="100%" verticalGap="0"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:HBox id="idTopContainer" width="100%" height="28" horizontalGap="2">
(top menu stuff goes here)
</mx:HBox>
<mx:HBox id="idBottomContainer" width="100%" height="100%" verticalScrollPolicy="off" clipContent="false">
(page stuff goes here)
</mx:HBox>
</mx:VBox>
</app:MyApplicationClass>
When I run it, it displays top panel with a fixed height, and a bottom panel with variable height. I expect the bottom panel's height to contain the remaining height, but it somehow overflows off-page.
The only way I found to fix this height issue (so far) is to programmatically set the height to be fixed instead of variable:
<mx:HBox id="idBottomContainer" width="100%" height="700" verticalScrollPolicy="off" clipContent="false">
(page stuff goes here)
</mx:HBox>
And code-behind:
package {
import mx.containers.HBox;
import mx.core.Application;
import mx.events.ResizeEvent;
// (...)
public class MyApplicationClass extends Application {
public var idBottomContainer:HBox;
// (...)
private function ON_CreationComplete (event:FlexEvent) : void {
// (...)
addEventListener(ResizeEvent.RESIZE, ON_Resize);
}
private function ON_Resize (event:Event) : void {
idBottomContainer.height = this.height - idTopContainer.height;
}
}
}
But this solution is too "dirty" and I'm looking for a more elegant way. Does anyone know an alternative?
Seems to me what you have ought to work. I have something similar working in countless screens. But if you're really stuck you could try to replace the VBox with a Canvas and do something like this:
<mx:Canvasid="idPageContainer" width="100%" height="100%" verticalGap="0"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:HBox id="idTopContainer" width="100%" height="28" horizontalGap="2">
(top menu stuff goes here)
</mx:HBox>
<mx:HBox id="idBottomContainer" width="100%" top="{idTopContainer.height}"
height="{idPageContainer.height - idTopContainer.height}"
verticalScrollPolicy="off" clipContent="false">
(page stuff goes here)
</mx:HBox>
</mx:Canvas>

size the height of a flex component to fill the space available on stage

Im trying to create a layout in flex using mxml, the layout contains a Canvas component and a Box. The layout should always be such that the Box sits at the bottom edge of the application and has a fixed height, whereas the Canvas fills the remaining stage area and does not overlap with the Box.
My MXML is as follows;
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%" layout="absolute" clipContent="false" verticalGap="0">
<mx:Canvas width="100%" height="100%" />
<mx:Box width="100%" height="30"></Box>
</mx:Module>
I've tried using a dynamic binding to set the height on the Canvas (height="{this.stage.height - 30}") but it yields the wrong results.
Is there a simple way to achieve what I am after without setting the height using Actionscript?
<Module layout="vertical" xmlns="...">
<Canvas width="100%" height="100%">
<HBox width="100%" height="30"/>
</Module>
By setting layout="vertical" the Module will work more or less like a VBox. The Canvas is set to fill 100% vertical and horizontal, but space will be left for the HBox, because it has an explicit height.
I haven't used Modules much, but this works:
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="100%"
height="100%"
>
<mx:Canvas left="0" right="0" top="0" bottom="0" />
<mx:HBox
width="100%"
height="50"
bottom="0"
>
....
</mx:HBox>
</mx:Application>
Hope that helps!
I was able to use;
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%" layout="absolute" clipContent="false" verticalGap="0">
<mx:Canvas bottom="30" left="0" right="0" top="0" />
<mx:Box width="100%" height="30"></Box>
</mx:Module>
This solved my issue, as the Canvas would fill the space available up to the Box. Setting the bottom property to 0 on the Canvas, would cause it to expand past the Box and fill the entire stage.

Resources