Most of the time, fl.containers.ScrollPane is fairly easy to use. In a recent project I used it on at least four different pages to display dynamic run-time content.
However, one of those pages seemed insistent on giving me problems. The problem was that the bottom of the dynamic content was being clipped. The scrollbar appeared, but the very bottom of the content was not visible.
My typical usage of the ScrollPane consists of three steps: First create the ScrollPane instance, second create the dynamic content, and third attach the content to the ScrollPane.
Here’s an example:
protected function build():void {
// Step 1: create the ScrollPane
var summarySP:ScrollPane = buildScrollPane();
summarySP.x = 40;
summarySP.y = 330;
this.addChild(summarySP);
// Step 2: create the content
content = buildContent();
// Step 3: attach content to ScrollPane
summarySP.source = content;
summarySP.invalidate();
}
protected function buildScrollPane():ScrollPane {
var sp:ScrollPane = new ScrollPane();
sp.setSize(550, 265);
sp.horizontalScrollPolicy = "off";
return sp;
}
protected function buildContent():Sprite {
var content:Sprite = new Sprite();
// header
var headerContent:Sprite = new Sprite();
var headerString:String;
var headerField:TextField;
var initX:int = 20;
var initY:int = 20;
var nextY:int = initY;
var yspace:int = 2;
var wspace:int = 12;
var i:int;
var maxI:int = selectedServicesLabel.length;
for (i = 0; i < maxI; i++) {
headerString = selectedServicesLabel[i];
headerField = new CustomTextField( headerString, styles );
headerField.x = initX;
headerField.y = nextY;
headerField.width = 500;
headerContent.addChild(headerField);
nextY += headerField.height;
}
content.addChild(headerContent);
// footer
var footerContent:Sprite = buildFooterContent();
content.addChild(footerContent);
return content;
}
Simple, right? Well, I included my erroneous code in that example. Did you spot it? Good for you! If not I’ll give you a big clue, the content, when it induced scrolling, consistently clipped the bottom by 20 pixels.
For those of you in the cheap seats that can’t immediately spot the problem, it is all due to setting the Y value of a child of the content. Although it is a child of the content, the content’s size does not account for the X or Y offset of its children. I go back and forth on whether this makes sense or not. Regardless, it remains true, the overall size of the content does not include the stage position of its children.
In this particular case, the design called for some whitespace, or padding, on the top and left of the dynamic content. The left/X padding didn’t matter to me, as you can see I disabled Horizontal scrolling in the ScrollPane. I was happy to have the content clipped off the right-hand side. But I could not sit idly by and allow the bottom to be clipped.
The quick fix I used was to keep the X and Y values as is, but then to fill up that unused space with some content. In this case I used the drawing API and created a 20×20 pixel transparent rectangle positioned at 0,0. This appeased the ScrollPane and finally the coveted bottom 20 pixels were included in the content’s measurements, and thus were displayed by the ScrollPane. Hurray!
Here’s the fix:
protected function buildContent():Sprite {
var content:Sprite = new Sprite();
// header
var headerContent:Sprite = new Sprite();
// top padding
headerContent.graphics.beginFill(0xffffff, 0);
headerContent.graphics.drawRect(0, 0, 20, 20 );
headerContent.graphics.endFill();
...
}
- ddb![]()
31 Mar 2010