Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Adobe AIR Development

Reply
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb
Accepted Solution

Variable height label in container with vertical flow

I'm trying to create a container with a label whose text length can be very long (ie comments).  The container is set to vertical flow so the label needs to reside width-wise within the container.  The height needs to be able to accommodate the text that will be contained within it.

 

The autoSize property of a the text field for a label include:

TextFieldAutoSize.NONE

TextFieldAutoSize.CENTER

TextFieldAutoSize.LEFT

TextFieldAutoSize.RIGHT

 

None of these will allow me to resize only the height.  There's a multiline and wordwrap property for both the Label and it's TextField.  I've had no luck with these.  I even tried using the containment property of the label set to Background.  All I end up with is a single line label that bleeds way off the screen.

 

I've tried the following (based on the post about centering text in a label without clipping):

 

package
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	
	import qnx.ui.core.Container;
	import qnx.ui.core.ContainerAlign;
	import qnx.ui.core.ContainerFlow;
	import qnx.ui.core.Containment;
	import qnx.ui.core.SizeMode;
	import qnx.ui.core.SizeUnit;
	import qnx.ui.display.Image;
	import qnx.ui.text.Label;
	
	
	[SWF(width="1024", height="600", backgroundColor="#CCCCCC", frameRate="30")]
	public class Test2 extends Sprite
	{	
		private var mainContainer:Container;
		private var titleLabel:Label;
		private var txtLabel:TextField;
		
		public function Test2()
		{
			super();
			
			mainContainer = new Container();
			mainContainer.margins = Vector.<Number>([20,20,20,20]);
			mainContainer.flow = ContainerFlow.VERTICAL;
			mainContainer.align = ContainerAlign.MID;
			mainContainer.debugColor = 0xff0000;
			
			addChild(mainContainer);
			mainContainer.setSize(stage.stageWidth, stage.stageHeight);
			
			titleLabel = new Label();
			titleLabel.text = "Here is a very long string to see if " +
				"this control will wrap or bleed into the other containers.  " +
				"Also, what is the effect of this long text on the " +
				"rest of the container.";
//			titleLabel.autoSize = TextFieldAutoSize.CENTER;

			var format:TextFormat = new TextFormat();
			format = new TextFormat();
			format.font = "Verdana";
			format.color = 0x000000;
			format.size = 26;
			titleLabel.format = format;
			
			titleLabel.textField.multiline;
			titleLabel.textField.wordWrap;
			titleLabel.size = 100;
			titleLabel.sizeUnit = SizeUnit.PERCENT;
			titleLabel.multiline;
			titleLabel.wordWrap;
			titleLabel.setSize(titleLabel.textWidth, titleLabel.textHeight);
			titleLabel.containment = Containment.BACKGROUND;
			titleLabel.graphics.beginFill(0xFF0000);
			titleLabel.graphics.drawRect(0,0,titleLabel.width, titleLabel.height);
			titleLabel.graphics.endFill();
			
			mainContainer.addChild(titleLabel);
			
		}
	}
}

 

Any help is greatly appreciated.

 

 

 

 

 

 

 

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb

Re: Variable height label in container with vertical flow

Oops.  It might have helped to give wordwrap a value like true. :smileytongue:

 

I have the height autosizing.  Now my only problem is the width. 

 

If I set titleLabel.width = mainContainer.width, the label spans the entire width of the container.  This is OK, but it doesn't take into account margins or padding for the container..

 

I tried using:

titleLabel.size = 100;

titleLabel.sizeUnit = SizeUnit.PERCENT;

 

This just sizes the label as width = 100.

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb

Re: Variable height label in container with vertical flow

I'm still trying to get my hadns around what shold be a simple problem.  I'm missing something in the interaction among Containers, Labels, the label's TextField, and widths and heights.

 

All I'm looking to do is to have a container which will populate labels with text comments, some of wihch can be long, in a vertical list.  The heights of the labels will vary depending on the length of the text (if the text needs to wrap), but I want the width to be the container's interiror width (taking padding into account).

 

I have a function to initialize the UI and another to populate the contents of labels based on data retrieved.  Do I have to call the container's 'layout()' or resize after populating them with data?  I've been hung up on this issue for some time now and it's really holding me up.

 

Do I want (or need) the Size, SizeUnit, and/or SizeMode set for the labels?  When I alter these values, it seems to have no effect on either the label's height or width (or the heght or width of the label's textfield).

 

Could someone please explain how this should be handled? 

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.
Developer
JRab
Posts: 2,462
Registered: ‎11-04-2010
My Device: Bold 9700

Re: Variable height label in container with vertical flow

[ Edited ]

hey wingflap,

 

sorry i totally missed this thread. but below is a code that does what i think you want. so first here's the code:

 

ContainerTest.as:

 

 

package
{
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.text.TextFieldAutoSize;
    
    import qnx.ui.core.Container;
    import qnx.ui.core.ContainerAlign;
    import qnx.ui.core.ContainerFlow;
    import qnx.ui.text.Label;

    
    [SWF(width="1024", height="600", backgroundColor="#CCCCCC", frameRate="30")]
    public class ContainerTest extends Sprite
    {    
        private var mainContainer:Container;
        
        /**
         * to keep things consistent, set the margin of the container to a variable so
         * if it changes, all you have to do is change it in one place
         **/
        
        private var containerMargin:int = 10;
        
        public function ContainerTest()
        {
            super();
            
            mainContainer = new Container();
            mainContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
            mainContainer.flow = ContainerFlow.VERTICAL;
            mainContainer.align = ContainerAlign.NEAR;
            
            mainContainer.setSize(300, 500);
            mainContainer.setPosition((stage.stageWidth / 2 ) - (mainContainer.width / 2), (stage.stageHeight / 2 ) - (mainContainer.height / 2));
            
            for (var i:int = 0; i < 6; i++)
            {
                var newComment:Label = new Label();
                
                newComment.text =     "This is some very long text. It is very very" +
                                    " long and should be line breaked eventually." +
                                    "here is some more text";
                
                /**
                 * The follow things should be set in order to get the proper sizing
                 * set for your comments.
                 **/
                
                newComment.autoSize = TextFieldAutoSize.LEFT;
                newComment.wordWrap = true;
                newComment.multiline = true;
                
                /**
                 * Do the height and width seperately. You cant get an accurate
                 * textHeight value until you set the proper height. with the
                 * height you will have to be intuitive and keep track of the
                 * label's container and what you set as the margin or
                 * alternatively you can use the mainContainer.margin[0-3] value.
                 *
                 * Also remember to multiply times 2 because the margin is on both
                 * sides not just one.
                 **/
                
                newComment.width = mainContainer.width - (containerMargin * 2);
                newComment.height = newComment.textHeight + 5;
                
                /**
                 * now just add it to the main container. dont worry about placement
                 **/
                
                mainContainer.addChild(newComment);
            }
            
            /**
             * Every time you add new object to a container, you must do the layout
             * method in order for it to layout all the children properly.
             **/
            
            mainContainer.layout();
            
            /**
             * Set a background for your container to see if everything is in
             * its proper place
             **/
            
            mainContainer.graphics.clear();
            mainContainer.graphics.beginFill(0xFF0000);
            mainContainer.graphics.drawRect(0,0,mainContainer.width,mainContainer.height);
            mainContainer.graphics.endFill();
            
            
            addChild(mainContainer);
            
        }
    }
}

 

 

There are a few comments that should be able to guide you through it. You had the basic concept down, just a few minor tweaks. Containers and lists are a tough thing to work with but they get easier after time. so what i did was create a for loop that imitates a bunch of comments. and then i set the properties that needed to be set to get the proper positioning.

 

as for your questions, you can retrieve the margins of your container using the .margins getter method. it will give you a vector much like an array of values. you have to use indexes depending on which margin you want.

 

and yes after you populate the data, you should call the .layout() method to layout all the children of the container. and as for the Size, SizeUnit and SizeMode, i avoid them completely. they get really confusing after a while. they arent independent properties. by setting them, you have to take into account other settings you set for the container you are using (e.g. flow, align, etc). they arent as intuitive as id like.

 

i hope that clears up a few things for you. if you have any more questions follow up and we'll be happy to help you out. good luck!

J. Rab (Blog) (Twitter)
--
1. If you liked my post or found it useful please click on the thumbs up and provide a Like!
2. If my post solved your problem please click on the Accept as Solution button. Much appreciated!

Approved Apps: OnTrack | ssShots | Hangman
Please use plain text.
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb

Re: Variable height label in container with vertical flow

@JRab,

 

Thanks for your quick reply.  I'm about to give your code a try, but, at first glance, I notice that your code is based on the premise of a fixed width container.  I really wanted to use a percentage to determine the width.  If I have a main container (with a horizontal flow) that sizes to the stage and then two sub containers (left size=20, sizeunit=percentage and right size 80, sizeunit percent) then I have no issue with changing the playbook's orientation.  The only problem is that through the debugger, I see that when I use Size and SizeUnit, the width and height property of the container are still null.

 

I'm afraid that your solution will want to scale if the playbook is rotated as opposed to simply resizing the containers as a percentage of the stage.

 

I'll try your code and then try to implement Size and SizeUnit and see what happens.  If you have any tips on how to get the container's width and height when it's been sized relatively as opposed to absolutely, I'd appreciate it.  I agree with you that there are too many interdependencies with these and that they are confusing.  I think I finally have a handle on the concepts (described in the developer manual) of flow, flow direction, perpendicular, and opposite direction.  I think that the only thing that is holding me back is the lack of one additional property value for autosize.  Left, right, and center adjust the right, left, and the bottom of your object.  None does no resizing.  If there was a 'Bottom" for autosize that left the left and right alone, but resized the height, I think that  might work.

 

I'll let you know how it goes.  Thanks for the help.  And if anything else occurs to you, please feel free to let me know.

 

Thanks.

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.
Developer
JRab
Posts: 2,462
Registered: ‎11-04-2010
My Device: Bold 9700

Re: Variable height label in container with vertical flow

hey wingflap,

 

i think i get what you are going for and i agree a little less fixed and more relative values are prolly the best way to go if you are taking rotating into account. below is what you described, one main container and two subcontainers one with 20% and the other with 80% width:

 

ContainerTest.as:

 

 

package
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.text.TextFieldAutoSize;
	
	import qnx.ui.core.Container;
	import qnx.ui.core.ContainerAlign;
	import qnx.ui.core.ContainerFlow;
	import qnx.ui.core.SizeUnit;
	import qnx.ui.text.Label;

	
	[SWF(width="1024", height="600", backgroundColor="#CCCCCC", frameRate="30")]
	public class ContainerTest extends Sprite
	{	
		private var mainContainer:Container;
		private var rightContainer:Container;
		private var leftContainer:Container;
		
		/**
		 * to keep things consistent, set the margin of the container to a variable so
		 * if it changes, all you have to do is change it in one place
		 **/
		
		private var containerMargin:int = 10;
		
		public function ContainerTest()
		{
			super();
			
			mainContainer = new Container();
			mainContainer.margins = Vector.<Number>([0,0,0,0]);
			mainContainer.flow = ContainerFlow.HORIZONTAL;
			mainContainer.align = ContainerAlign.NEAR;
			
			/**
			 * create a left and right container. the right will hold all of your comments.
			 * the left will hold some arbritary data.
			 **/
			
			rightContainer = new Container();
			rightContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
			rightContainer.flow = ContainerFlow.VERTICAL;
			rightContainer.align = ContainerAlign.NEAR;
			rightContainer.size = 20;
			rightContainer.sizeUnit = SizeUnit.PERCENT;
			
			leftContainer = new Container();
			leftContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
			leftContainer.flow = ContainerFlow.VERTICAL;
			leftContainer.align = ContainerAlign.NEAR;
			leftContainer.size = 80;
			leftContainer.sizeUnit = SizeUnit.PERCENT;
			
			/**
			 * add the two sub containers to the main container
			 **/
			
			mainContainer.addChild(leftContainer);
			mainContainer.addChild(rightContainer);
			
			mainContainer.setSize(stage.stageWidth, stage.stageHeight);
			
			for (var i:int = 0; i < 6; i++)
			{
				var newComment:Label = new Label();
				
				newComment.text = 	"This is some very long text. It is very very" +
									" long and should be line breaked eventually. " +
									"here is some more text";
				
				/**
				 * The follow things should be set in order to get the proper sizing
				 * set for your comments.
				 **/
				
				newComment.autoSize = TextFieldAutoSize.LEFT;
				newComment.wordWrap = true;
				newComment.multiline = true;
				
				/**
				 * Do the height and width seperately. You cant get an accurate
				 * textHeight value until you set the proper height. with the
				 * height you will have to be intuitive and keep track of the
				 * label's container and what you set as the margin or
				 * alternatively you can use the rightContainer.margin[0-3] value.
				 * 
				 * Also remember to multiply times 2 because the margin is on both
				 * sides not just one.
				 **/
				
				newComment.width = rightContainer.width - (containerMargin * 2);
				newComment.height = newComment.textHeight + 5;
				
				/**
				 * now just add it to the rightContainer. dont worry about placement
				 **/
				
				rightContainer.addChild(newComment);
			}
			
			/**
			 * Every time you add new object to a container, you must do the layout
			 * method in order for it to layout all the children properly.
			 **/
			
			rightContainer.layout();
			
			/**
			 * Set a background for your containers to see if everything is in
			 * its proper place
			 **/
			
			rightContainer.graphics.clear();
			rightContainer.graphics.beginFill(0xFF0000);
			rightContainer.graphics.drawRect(0,0,rightContainer.width,rightContainer.height);
			rightContainer.graphics.endFill();
			
			leftContainer.graphics.clear();
			leftContainer.graphics.beginFill(0xFFFF00);
			leftContainer.graphics.drawRect(0,0,leftContainer.width,leftContainer.height);
			leftContainer.graphics.endFill();
			
			
			addChild(mainContainer);
			
		}
	}
}

 

Try running that and lemme know if thats what you are looking for. you are able to get the width of the "comment" container from what i've tested out as long as you add the comment container and set the size of the main contaienr prior to retrieving the width of the sub container. hope that helps some. good luck!

 

J. Rab (Blog) (Twitter)
--
1. If you liked my post or found it useful please click on the thumbs up and provide a Like!
2. If my post solved your problem please click on the Accept as Solution button. Much appreciated!

Approved Apps: OnTrack | ssShots | Hangman
Please use plain text.
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb

Re: Variable height label in container with vertical flow

Your code worked well with an 80% left and a 20% right.  So I decided to see what it would do if the containers changed size.  I added a header with a button to switch left and right's size from 80-20 to 20-80.  This did not change the widths of the labels contained in rightContainer.

 

I figured that if the width and heights could be recalculated to take into account the change in container size, this thing might be actually going some where.  I hacked a containerResize function but don't know the proper syntax for walking through the rightContainer child objects via a for each loop.  I'm not sure what objects actually reside within the Container, so I took a jab at just labels.  If you can get the for each to work, this function can be parameterized so that it can be a single renderer/resizer that can be called both for initial UI and resize events.

 

Anyway, here's what I've got:

 

package
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextFieldAutoSize;
	
	import qnx.ui.buttons.LabelButton;
	import qnx.ui.core.Container;
	import qnx.ui.core.ContainerAlign;
	import qnx.ui.core.ContainerFlow;
	import qnx.ui.core.Containment;
	import qnx.ui.core.SizeUnit;
	import qnx.ui.text.Label;
	
	
	[SWF(width="1024", height="600", backgroundColor="#CCCCCC", frameRate="30")]
	public class ContainerTest extends Sprite
	{	
		private var mainContainer:Container;
// added header to hold a button //
		private var header:Container;
		private var rightContainer:Container;
		private var leftContainer:Container;
		
// Added a button to switch Container widths //
		private var btnSwitch:LabelButton;
		private var newComment:Label;
		/**
		 * to keep things consistent, set the margin of the container to a variable so
		 * if it changes, all you have to do is change it in one place
		 **/
		
		private var containerMargin:int = 10;
		
		public function ContainerTest()
		{
			super();
			
			mainContainer = new Container();
			mainContainer.margins = Vector.<Number>([0,0,0,0]);
			mainContainer.flow = ContainerFlow.HORIZONTAL;
			mainContainer.align = ContainerAlign.NEAR;
			
			/**
			 * create a left and right container. the right will hold all of your comments.
			 * the left will hold some arbritary data.
			 **/
			
			rightContainer = new Container();
			rightContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
			rightContainer.flow = ContainerFlow.VERTICAL;
			rightContainer.align = ContainerAlign.NEAR;
			rightContainer.size = 80;
			rightContainer.sizeUnit = SizeUnit.PERCENT;
			rightContainer.scrollRect;
			
			leftContainer = new Container();
			leftContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
			leftContainer.flow = ContainerFlow.VERTICAL;
			leftContainer.align = ContainerAlign.NEAR;
			leftContainer.size = 20;
			leftContainer.sizeUnit = SizeUnit.PERCENT;
			
//created a header for the button to change left and right container widths //
			header = new Container();
			header.flow = ContainerFlow.HORIZONTAL;
			leftContainer.align = ContainerAlign.MID;
			header.size = 10;
			header.sizeUnit = SizeUnit.PERCENT;
			header.containment = Containment.DOCK_TOP;
			
			/**
			 * add the two sub containers to the main container
			 **/
			
			mainContainer.addChild(leftContainer);
			mainContainer.addChild(rightContainer);
			mainContainer.addChild(header);
			
			mainContainer.setSize(stage.stageWidth, stage.stageHeight);
			
// the button //
			btnSwitch = new LabelButton();
			btnSwitch = new LabelButton();
			btnSwitch.label = "Switch";
			btnSwitch.size = 20;
			btnSwitch.sizeUnit = SizeUnit.PERCENT;
			btnSwitch.addEventListener(MouseEvent.CLICK,onSwitch);
			header.addChild(btnSwitch);
			
			for (var i:int = 0; i < 6; i++)
			{
				newComment = new Label();
				
				newComment.text = 	"This is some very long text. It is very very" +
					" long and should be line breaked eventually. " +
					"here is some more text";
				
				/**
				 * The follow things should be set in order to get the proper sizing
				 * set for your comments.
				 **/
				
				newComment.autoSize = TextFieldAutoSize.LEFT;
				newComment.wordWrap = true;
				newComment.multiline = true;
				
				/**
				 * Do the height and width seperately. You cant get an accurate
				 * textHeight value until you set the proper height. with the
				 * height you will have to be intuitive and keep track of the
				 * label's container and what you set as the margin or
				 * alternatively you can use the rightContainer.margin[0-3] value.
				 * 
				 * Also remember to multiply times 2 because the margin is on both
				 * sides not just one.
				 **/
				
				newComment.width = rightContainer.width - (containerMargin * 2);
				newComment.height = newComment.textHeight + 5;
				
				/**
				 * now just add it to the rightContainer. dont worry about placement
				 **/
				
				rightContainer.addChild(newComment);
			}
			
			/**
			 * Every time you add new object to a container, you must do the layout
			 * method in order for it to layout all the children properly.
			 **/
			
			rightContainer.layout();
			
			/**
			 * Set a background for your containers to see if everything is in
			 * its proper place
			 **/
			
			rightContainer.graphics.clear();
			rightContainer.graphics.beginFill(0xFF0000);
			rightContainer.graphics.drawRect(0,0,rightContainer.width,rightContainer.height);
			rightContainer.graphics.endFill();
			
			leftContainer.graphics.clear();
			leftContainer.graphics.beginFill(0xFFFF00);
			leftContainer.graphics.drawRect(0,0,leftContainer.​width,leftContainer.height);
			leftContainer.graphics.endFill();
			
			
			addChild(mainContainer);
			
		}
/**
 *  Function resizeComments
 *  This function simply iterates through the children of the right Container.
 *  It resets the widths and heights, does the layout, then the graphics stuff.
 **/
		private function resizeComments():void
		{
			for each (var item:Label in rightContainer)
			{
			item.width = rightContainer.width - (containerMargin * 2);
			item.height = item.textHeight + 5;
			}
			rightContainer.layout();

			rightContainer.graphics.clear();
			rightContainer.graphics.beginFill(0xFF0000);
			rightContainer.graphics.drawRect(0,0,rightContainer.width,rightContainer.height);
			rightContainer.graphics.endFill();
			
			leftContainer.graphics.clear();
			leftContainer.graphics.beginFill(0xFFFF00);
			leftContainer.graphics.drawRect(0,0,leftContainer.​width,leftContainer.height);
			leftContainer.graphics.endFill();
		}
		protected function onSwitch(event:MouseEvent):void
		{
			// changes the size of the left/right containers
			// and then calls base.layout() so that all of
			// the base container's children are re-configured
			// and redrawn
			if (leftContainer.size == 80)
			{
				leftContainer.size = 20;
				rightContainer.size = 80;
			}
			else
			{
				leftContainer.size = 80;
				rightContainer.size = 20;
			}
		
			resizeComments();
			leftContainer.layout();
			rightContainer.layout();
			mainContainer.layout();
		}
	}
}

 Not sure if it needs all the .layout() calls at the end of the function.

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb

Re: Variable height label in container with vertical flow

I just discovered something interesting.  Once the container is established with the labels sizing to the width of the container and their heights based on the amount of text in the label, changing container size again requires an extra step.

 

If you are using this method to fit labels into a container, whenever you change the size, you need to call the main container's .layout() method twice.  When you change the text in the label, you need to call .layout().  This gets the widths aligned, but does nothing for the height.  After you call it for the first time, the label's width changes.  Then you set the height based on the text's adjusted height.  Now you must call .layout() a second time to adjust the heights.

 

After doing this, when I click the button to change the sizes of the left and right containers, the labels all resize correctly.

 

Still waiting for syntax to enumerate labels contained withing a container.:manwink:

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.
Developer
JRab
Posts: 2,462
Registered: ‎11-04-2010
My Device: Bold 9700

Re: Variable height label in container with vertical flow

hey,

 

sorry totally missed this thead (again) hah. i thought you had it solved and then ran the code and saw the problem and then your comment about the enumerating the label made it stick out more lol. anyways, below is the code to go through all the label objects in a given container and resize it properly. you need to call the mainContainer.layout() before doing your resizeComments() method so the rightContainer knows its own width and you can use it. after that you dont need anymroe .layout() method calls except the rightContainer.layout() after your resize the comments. here is the code:

 

 

package
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextFieldAutoSize;

import qnx.ui.buttons.LabelButton;
import qnx.ui.core.Container;
import qnx.ui.core.ContainerAlign;
import qnx.ui.core.ContainerFlow;
import qnx.ui.core.Containment;
import qnx.ui.core.SizeUnit;
import qnx.ui.text.Label;


[SWF(width="1024", height="600", backgroundColor="#CCCCCC", frameRate="30")]
public class ContainerTest extends Sprite
{
private var mainContainer:Container;
// added header to hold a button //
private var header:Container;
private var rightContainer:Container;
private var leftContainer:Container;

// Added a button to switch Container widths //
private var btnSwitch:LabelButton;
private var newComment:Label;
/**
* to keep things consistent, set the margin of the container to a variable so
* if it changes, all you have to do is change it in one place
**/

private var containerMargin:int = 10;

public function ContainerTest()
{
super();

mainContainer = new Container();
mainContainer.margins = Vector.<Number>([0,0,0,0]);
mainContainer.flow = ContainerFlow.HORIZONTAL;
mainContainer.align = ContainerAlign.NEAR;

/**
* create a left and right container. the right will hold all of your comments.
* the left will hold some arbritary data.
**/

rightContainer = new Container();
rightContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
rightContainer.flow = ContainerFlow.VERTICAL;
rightContainer.align = ContainerAlign.NEAR;
rightContainer.size = 80;
rightContainer.sizeUnit = SizeUnit.PERCENT;
rightContainer.scrollRect;

leftContainer = new Container();
leftContainer.margins = Vector.<Number>([containerMargin,containerMargin,containerMargin,containerMargin]);
leftContainer.flow = ContainerFlow.VERTICAL;
leftContainer.align = ContainerAlign.NEAR;
leftContainer.size = 20;
leftContainer.sizeUnit = SizeUnit.PERCENT;

//created a header for the button to change left and right container widths //
header = new Container();
header.flow = ContainerFlow.HORIZONTAL;
leftContainer.align = ContainerAlign.MID;
header.size = 10;
header.sizeUnit = SizeUnit.PERCENT;
header.containment = Containment.DOCK_TOP;

/**
* add the two sub containers to the main container
**/

mainContainer.addChild(leftContainer);
mainContainer.addChild(rightContainer);
mainContainer.addChild(header);

mainContainer.setSize(stage.stageWidth, stage.stageHeight);

// the button //
btnSwitch = new LabelButton();
btnSwitch = new LabelButton();
btnSwitch.label = "Switch";
btnSwitch.size = 20;
btnSwitch.sizeUnit = SizeUnit.PERCENT;
btnSwitch.addEventListener(MouseEvent.CLICK,onSwitch);
header.addChild(btnSwitch);

for (var i:int = 0; i < 6; i++)
{
newComment = new Label();

newComment.text = "This is some very long text. It is very very" +
" long and should be line breaked eventually. " +
"here is some more text";

/**
* The follow things should be set in order to get the proper sizing
* set for your comments.
**/

newComment.autoSize = TextFieldAutoSize.LEFT;
newComment.wordWrap = true;
newComment.multiline = true;

/**
* Do the height and width seperately. You cant get an accurate
* textHeight value until you set the proper height. with the
* height you will have to be intuitive and keep track of the
* label's container and what you set as the margin or
* alternatively you can use the rightContainer.margin[0-3] value.
*
* Also remember to multiply times 2 because the margin is on both
* sides not just one.
**/

newComment.width = rightContainer.width - (containerMargin * 2);
newComment.height = newComment.textHeight + 5;

/**
* now just add it to the rightContainer. dont worry about placement
**/

rightContainer.addChild(newComment);
}

/**
* Every time you add new object to a container, you must do the layout
* method in order for it to layout all the children properly.
**/

rightContainer.layout();

/**
* Set a background for your containers to see if everything is in
* its proper place
**/

rightContainer.graphics.clear();
rightContainer.graphics.beginFill(0xFF0000);
rightContainer.graphics.drawRect(0,0,rightContainer.width,rightContainer.height);
rightContainer.graphics.endFill();

leftContainer.graphics.clear();
leftContainer.graphics.beginFill(0xFFFF00);
leftContainer.graphics.drawRect(0,0,leftContainer.​width,leftContainer.height);
leftContainer.graphics.endFill();


addChild(mainContainer);

}
/**
* Function resizeComments
* This function simply iterates through the children of the right Container.
* It resets the widths and heights, does the layout, then the graphics stuff.
**/
private function resizeComments():void
{
for (var i:int = 0; i < rightContainer.numChildren; i++)
{
var item:* = rightContainer.getChildAt(i);

if (item is Label)
{
item.width = rightContainer.width - (containerMargin * 2);
item.height = item.textHeight + 5;
}
}

rightContainer.layout();

rightContainer.graphics.clear();
rightContainer.graphics.beginFill(0xFF0000);
rightContainer.graphics.drawRect(0,0,rightContainer.width,rightContainer.height);
rightContainer.graphics.endFill();

leftContainer.graphics.clear();
leftContainer.graphics.beginFill(0xFFFF00);
leftContainer.graphics.drawRect(0,0,leftContainer.​width,leftContainer.height);
leftContainer.graphics.endFill();
}
protected function onSwitch(event:MouseEvent):void
{
// changes the size of the left/right containers
// and then calls base.layout() so that all of
// the base container's children are re-configured
// and redrawn
if (leftContainer.size == 80)
{
leftContainer.size = 20;
rightContainer.size = 80;
}
else
{
leftContainer.size = 80;
rightContainer.size = 20;
}

mainContainer.layout();
resizeComments();
}
}
}

 

hope that clears a few things up! good luck!

 

J. Rab (Blog) (Twitter)
--
1. If you liked my post or found it useful please click on the thumbs up and provide a Like!
2. If my post solved your problem please click on the Accept as Solution button. Much appreciated!

Approved Apps: OnTrack | ssShots | Hangman
Please use plain text.
Developer
Wingflap
Posts: 118
Registered: ‎01-22-2011
My Device: Bold 9650 and Playbook 16gb

Re: Variable height label in container with vertical flow

@JRab,

 

Thanks so much!  not only does this work for expanding/contracting containers, but it also makes resizing for orientation change very simple without messing up the label layout. One final question on this, though.  Is there any scroll/swipe functionality that would make it possible to swipe/scroll if the labels go beyond the bottom of the container?  Would this be an event applied to the container itself?

-------------------------------------------------------------------------------------------
Approved Apps: Barry Black

Loving my new Playbook!
Please use plain text.