A Flash Developer Resource Site

Page 1 of 3 123 LastLast
Results 1 to 20 of 41

Thread: Positioning MCs according to height

  1. #1
    Member
    Join Date
    Mar 2007
    Posts
    69

    Question Positioning MCs according to height

    I need to create the attached jpg, but i'm not sure of the best way to tackle it.

    The news posts are loaded from XML and will vary in height so they need to somehow be sorted so that if one is going to come off the page, then it's put into the next page - where the user will click the scroll buttons to view.

    Would something like this be a good way to tackle this?

    1/ Load article from XML
    2/ Create a postMC_0 and add article bits to it (date, title, body)
    3/ Record height
    4/ Create a newsColumn_0 and add postMC_0 to it

    Then a loop:

    5/ Load next article

    6/ Create a postMC_1 and add article bits to it

    7/ If difference between postMC_0 height and newsColumn_0 height is greater than the height of postMC_1, then add postMC_1 to newsColumn_0.

    8/ If not, then create newsColumn_1 and add postMC_1 to it.

    9/ Loop back to 5 (increasing the numbers each time, so postMC_2, etc)


    Then just make the scroll buttons function according to how many columns have been created..


    Any advise would be greatly appreciated.

    Many thanks.
    Attached Images Attached Images

  2. #2
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Do not use a naming convention when you really want a collection. That is, don't create postMC_0, postMC_1, etc, but create an array for them instead.
    Code:
    var posts:Array = [];
    posts.push(somepost);
    Similarly for the columns. Though I don't think you actually need multiple columns unless they will actually be showing at the same time. You could just move the posts in and out of the column.

  3. #3
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Do not use a naming convention when you really want a collection. That is, don't create postMC_0, postMC_1, etc, but create an array for them instead.
    Code:
    var posts:Array = [];
    posts.push(somepost);
    Similarly for the columns. Though I don't think you actually need multiple columns unless they will actually be showing at the same time. You could just move the posts in and out of the column.

  4. #4
    Member
    Join Date
    Mar 2007
    Posts
    69
    Thanks for the reply..

    how would i separate each post each containing 3 elements, if i'm using an array? Wouldn't it then just be a really long array of info, rather than being organised?

    Or would i have an array per post?

    This is my AS so far... using the post_mc idea..

    Actionscript Code:
    for (var i:int = 0; i<myXML.news.length(); i++){
                   
                    var newsPost_mc = new MovieClip();
                    var newsDate = new TextField();
                    var newsTitle = new TextField();
                    var newsBody = new TextField();
                   
                    newsDate.embedFonts = true;
                    //newsDate.autoSize = TextFieldAutoSize.LEFT;
                    //newsDate.antiAliasType = AntiAliasType.ADVANCED;
                    newsDate.setTextFormat(dateFormat);
                   
                    newsPost_mc.name = "newsPost_mc_"+i;
                   
                    newsDate.name = "newsDate"+i;
                    newsDate.htmlText = myXML.news.newsDate[i];
                   
                    newsTitle.name = "newsTitle"+i;
                    newsTitle.htmlText = myXML.news.newsTitle[i];
                   
                    newsBody.name = "newsBody"+i;
                    newsBody.htmlText = myXML.news.newsBody[i];
                   
                    sectionpage.newsColumn.addChild(newsPost_mc);
                    newsPost_mc.addChild(newsDate);
                    newsPost_mc.addChild(newsTitle);
                    newsPost_mc.addChild(newsBody);
                   
                    newsPost_mc.y = i*100;
                    newsTitle.y = 50;
                    newsTitle.x = 0;
                    newsDate.x = 0;
                    newsDate.y= 0;
                    newsBody.x = 50;
                    newsBody.y = 50;
       
                }

  5. #5
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    The array has nothing to do with the visual representation. It's a logical construct that lets you deal with a collection of items in an easy way.

    Well, I'd make a class for NewsPost, but that looks like a decent start. Why are you putting each at i*100? You could put them at the last NewsPost height + last NewsPost y. That would have them follow each other exactly. Are you trying to do the multicolumn thing now or just get one working first?

  6. #6
    Member
    Join Date
    Mar 2007
    Posts
    69
    I was just putting i*100 temporarily to space the posts out while i worked on them.

    This is my AS now.. finding it difficult to position them according to the last post's Y, they seem to be spacing themselves a lot further apart than they should.. have i got this all wrong?

    Actionscript Code:
    for (var i:int = 0; i<myXML.news.length(); i++){
                   
                    var newsPost_mc = new MovieClip();
                    newsPost_mc.opaqueBackground = 0xCCCCCC;
                   
                    var newsDate = new TextField();
                    var newsTitle = new TextField();
                    var newsBody = new TextField();
                   
                    newsDate.embedFonts = true;
                    newsTitle.embedFonts = true;
                    newsBody.embedFonts = true;
                    newsBody.wordWrap = true;
                    newsBody.autoSize = TextFieldAutoSize.LEFT;

                    newsDate.antiAliasType = AntiAliasType.ADVANCED;
                    newsTitle.antiAliasType = AntiAliasType.ADVANCED;
                    newsBody.antiAliasType = AntiAliasType.ADVANCED;
                   
                    newsDate.defaultTextFormat = dateFormat;
                    newsTitle.defaultTextFormat = dateFormat;
                    newsBody.styleSheet = IStyleSheet(Gaia.api.getPage("index").assets.stylesheet).style;
                   
                    newsPost_mc.name = "newsPost_mc_"+i;
                   
                    newsDate.name = "newsDate"+i;
                    newsDate.text = myXML.news.newsDate[i];
                   
                    newsTitle.name = "newsTitle"+i;
                    newsTitle.text = myXML.news.newsTitle[i];
                   
                    newsBody.name = "newsBody"+i;
                    newsBody.htmlText = myXML.news.newsBody[i];
                   
                    sectionpage.newsColumn.addChild(newsPost_mc);
                    newsPost_mc.addChild(newsDate);
                    newsPost_mc.addChild(newsTitle);
                    newsPost_mc.addChild(newsBody);
                   
                    // Positions & Sizing
                    var lastMCh:int = newsPost_mc.height;
                   
                    if (i<1)
                    {
                        newsPost_mc.y = 0; // Put first one at top
                    }
                    else
                    {
                        var lastMCy:int = newsPost_mc.y;
                        newsPost_mc.y = lastMCh + lastMCy;
                    }
                   
                   
                    newsTitle.y = 0;
                    newsDate.width=100;
                    newsDate.height=30;
                    newsTitle.width = 300;
                    newsTitle.height = 30;
                    newsTitle.x = 80;
                    newsDate.x = 0;
                    newsDate.y= 0;
                    newsBody.x = 80;
                    newsBody.y = newsTitle.height;
                    newsBody.width=350;
                   
               
                }

    Many thanks.

  7. #7
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    It looks like you did not set autosize on the title or date, but you are explicitly sizing them. Your lastMCh and lastMCy aren't actually the lastMC's anything. You're setting them to the properties of the same ones you're about to manipulate. And you were trying to use the height of newsPost before you'd sized and placed all its content.

    Also, you're not even using those names, so don't bother with them. And if you were to bother naming them, do not append the index. You should be putting each newsPost in an array, and then you can just get the post parts from that post.

    Code:
    var posts:Array = [];
    var lastY:Number = 0;
    for (var i:int = 0; i<myXML.news.length(); i++){
      var newsPost_mc:Sprite = new Sprite();
      posts.push(newsPost_mc); 
    
      newsPost_mc.opaqueBackground = 0xCCCCCC;
                   
      var newsDate:TextField = new TextField();
      var newsTitle:TextField = new TextField();
      var newsBody:TextField = new TextField();
                   
      newsDate.embedFonts = true;
      newsTitle.embedFonts = true;
      newsBody.embedFonts = true;
      newsBody.wordWrap = true;
      newsBody.autoSize = TextFieldAutoSize.LEFT;
    
      newsDate.antiAliasType = AntiAliasType.ADVANCED;
      newsTitle.antiAliasType = AntiAliasType.ADVANCED;
      newsBody.antiAliasType = AntiAliasType.ADVANCED;
                  
      newsDate.defaultTextFormat = dateFormat;
      newsTitle.defaultTextFormat = dateFormat;
      newsBody.styleSheet = IStyleSheet(Gaia.api.getPage("index").assets.stylesheet).style;
                   
      newsDate.text = myXML.news.newsDate[i];
      newsTitle.text = myXML.news.newsTitle[i];
      newsBody.htmlText = myXML.news.newsBody[i];
                   
      sectionpage.newsColumn.addChild(newsPost_mc);
      newsPost_mc.addChild(newsDate);
      newsPost_mc.addChild(newsTitle);
      newsPost_mc.addChild(newsBody);
                   
      // Positions & Sizing
      newsTitle.y = 0;
      newsDate.width=100;
      newsDate.height=30;
      newsTitle.width = 300;
      newsTitle.height = 30;
      newsTitle.x = 80;
      newsDate.x = 0;
      newsDate.y= 0;
      newsBody.x = 80;
      newsBody.y = newsTitle.height;
      newsBody.width=350;
    
      newsPost_mc.y = lastY;
      lastY += newsPost_mc.height;
               
    }
    I would take most of that code which builds the post and put it in a NewsPost class.

    Code:
    package {
      //imports here.
      public class NewsPost extends Sprite{
        public var newsDate:TextField;
        public var newsTitle:TextField;
        public var newsBody:TextField;
    
        public function NewsPost(date:String, title:String, body:String, dateFormat:TextFormat){
          opaqueBackground = 0xCCCCCC;
                   
          newsDate = new TextField();
          newsTitle = new TextField();
          newsBody = new TextField();
                   
          newsDate.embedFonts = true;
          newsTitle.embedFonts = true;
          newsBody.embedFonts = true;
          newsBody.wordWrap = true;
          newsBody.autoSize = TextFieldAutoSize.LEFT;
    
          newsDate.antiAliasType = AntiAliasType.ADVANCED;
          newsTitle.antiAliasType = AntiAliasType.ADVANCED;
          newsBody.antiAliasType = AntiAliasType.ADVANCED;
                  
          newsDate.defaultTextFormat = dateFormat;
          newsTitle.defaultTextFormat = dateFormat;
          newsBody.styleSheet = IStyleSheet(Gaia.api.getPage("index").assets.stylesheet).style;
                   
          newsDate.text = date;
          newsTitle.text = title;
          newsBody.htmlText = body;
                   
          addChild(newsDate);
          addChild(newsTitle);
          addChild(newsBody);
                   
          // Positions & Sizing
          newsTitle.y = 0;
          newsDate.width=100;
          newsDate.height=30;
          newsTitle.width = 300;
          newsTitle.height = 30;
          newsTitle.x = 80;
          newsDate.x = 0;
          newsDate.y= 0;
          newsBody.x = 80;
          newsBody.y = newsTitle.height;
          newsBody.width=350;
        }
    
      }
    
    }
    And then you can shorten the loop to:
    Code:
    var posts:Array = [];
    var lastY:Number = 0;
    for (var i:int = 0; i<myXML.news.length(); i++){
      //may have to convert these with toString if they don't just work
      var date:String = myXML.news.newsDate[i];
      var title:String = myXML.news.newsTitle[i];
      var body:String = myXML.news.newsBody[i];
      var newsPost:NewsPost = new NewsPost(date, title, body, dateFormat);
      posts.push(newsPost); 
    
      sectionpage.newsColumn.addChild(newsPost);
      newsPost.y = lastY;
      lastY += newsPost.height;
               
    }

  8. #8
    Member
    Join Date
    Mar 2007
    Posts
    69
    Thanks so much for that, it works. Now trying to understand why this works and where i was going wrong...I think i get it:

    1/ Create an empty array called posts
    2/ Then with each loop:
    - create a newsPost_mc as a Sprite (why not movieclip?)
    - add a newsPost_mc to the posts array
    - Set all the styling, assign the xml text to each textfield
    - set newsPost_mc.y to y (on first loop will be 0)
    - record current newsPost_mc y + height ready for next loop

    Just to help me understand - Why is it necessary to use an Array here? Will it help for the next part of only showing posts that fit into the container mc?

  9. #9
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    The array is not strictly necessary here. But whenever you have a collection of objects that you will want to manipulate together, it's a good idea. Basically, if you were ever going to name something "somename_"+i, you should be using an array instead.

    I used Sprite rather than MovieClip because we didn't need anything that MovieClip provides that Sprite doesn't. newsPost does not have frames, and does not need to be dynamic. It does need to be a DisplayObjectContainer, so the thing that most closely suits those requirements is Sprite. Until we build our own NewsPost class.

    Yes, you could go through the array after building it like this and move stuff into other columns, but if you're actually creating separate columns, you could have partitioned the posts in the first loop. Let's say sectionpage can have an arbitrary number of columns that are at most columnHeight tall. We'll store these columns in an array property of sectionpage called columns. It's up to you how you want to show them, whether they are all displayed at once or you replace the showing one as you move through. I'll write code assuming they're all showing at once.

    Code:
    var posts:Array = [];
    var lastY:Number = 0;
    //assume sectionpage.columns is an array containing one empty column.
    //assume columnHeight is a Number and is already set.
    var column:DisplayObjectContainer = sectionpage.columns[0];
    for (var i:int = 0; i<myXML.news.length(); i++){
      //may have to convert these with toString if they don't just work
      var date:String = myXML.news.newsDate[i];
      var title:String = myXML.news.newsTitle[i];
      var body:String = myXML.news.newsBody[i];
      var newsPost:NewsPost = new NewsPost(date, title, body, dateFormat);
      posts.push(newsPost); 
      if (lastY + newsPost.height > columnHeight){
       var nextX:Number = column.x + column.width;
       column = new Sprite();
       column.x = nextX;
       sectionpage.columns.push(column);
       sectionpage.addChild(column);
       lastY = 0;
      }
    
      column.addChild(newsPost);
      newsPost.y = lastY;
      lastY += newsPost.height;
               
    }
    For extra credit, what happens when a single post is taller than columnHeight?

    Again, we are not using these arrays yet, but we're setting them up because we almost certainly will want easy access to columns and posts. You may want to change posts from its current scope to each column having its own array of posts. Or you may want both. It depends on what you will be doing with them later.

  10. #10
    Member
    Join Date
    Mar 2007
    Posts
    69
    The news posts shouldn't be longer than the columnHeight, will just place a word limit on it for now.

    So currently the news posts are loading into newsColumn movieclip which is placed on the stage.. so to make way for the columns, this needs to be scrapped?

    And in its place, i create an array here, and columnHeight var:

    code:

    var posts:Array = [];
    var lastY:Number = 0;
    var columns:Array = [];
    var columnHeight:Number = 330;



    It's giving me an error like this, i guess i've got the columns array part wrong?

  11. #11
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    The code above assumes that columns is a property of sectionpage.

    You don't have to scrap newsColumn. Just put it in as the first entry of columns. In fact, that's what I intended above.

  12. #12
    Member
    Join Date
    Mar 2007
    Posts
    69
    sorry i'm a bit stuck here. how do i make the columns a property of sectionpage?

  13. #13
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    If sectionpage is a MovieClip, and therefore dynamic, you can do it like this:
    Code:
    sectionpage.columns =[];
    sectionpage.columns.push(newsColumn);
    If you do that from within code on sectionpage, replace "sectionpage" with "this". If you have created your own class for sectionpage... no, you haven't done that.

  14. #14
    Member
    Join Date
    Mar 2007
    Posts
    69
    hmm. This gives me an Error #1009: Cannot access a property or method of a null object reference.

    I haven't created my own class for sectionpage but this whole section is within a document class for newspage.fla.

  15. #15
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Then sectionpage doesn't exist yet where you put that code. It might be best to put it on sectionpage itself, or just after you create sectionpage (in the frame where it shows up).

  16. #16
    Member
    Join Date
    Mar 2007
    Posts
    69
    are you sure it's that? As sectionpage is already declared..

    Actionscript Code:
    public class NewsPage extends AbstractPage
        {

            // Declare instances on stage in NewsPage.fla
            public var bgbutton:SimpleButton;
            public var closebutton:SimpleButton;

            public var sectionpage:MovieClip;
            public var newsColumn:MovieClip;

            public var textTitle:TextField;
            public var textBody:TextField;

            public var myXML:XML;

            public function NewsPage()
            {
                super();
            }
            override public function transitionIn():void
            {
                super.transitionIn();
                gotoAndPlay("in");

                sectionpage.textBody.styleSheet = IStyleSheet(Gaia.api.getPage("index").assets.stylesheet).style;

                var myXML:XML = IXml(assets.newsContent).xml;

                sectionpage.textTitle.htmlText = myXML.sectionContent.title;
                sectionpage.textBody.htmlText = myXML.sectionContent.body;


                var dateFormat:TextFormat = new TextFormat();
                dateFormat.color = 0xFFFFFF;
                dateFormat.font = Gaia.api.getFontName("DIN");
                dateFormat.size = 18;

                var posts:Array = [];
                var lastY:Number = 0;
                //sectionpage.columns:Array = [];
               
                sectionpage.columns = [];
                sectionpage.columns.push(newsColumn);
               
                var columnHeight:Number = 330;
               
                var column:DisplayObjectContainer = sectionpage.columns[0];

  17. #17
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Code:
                sectionpage.columns:Array = [];
    This is invalid syntax. It should have resulted in a compile error before you ever had a chance to get the runtime 1009 error. Remove that line since the next one down does it the right way.

    I was assuming that newsColumn was a child of sectionpage, since it made sense to me that a section would have columns. That does not appear to be the case, so you can try to put columns on the NewsPage itself. Where you have sectionpage.columns above, replace it with just columns. And declare a columns array variable in NewsPage. Also, obviously, add the new column to "this" rather than sectionpage.

  18. #18
    Member
    Join Date
    Mar 2007
    Posts
    69
    Sorry i was actually just experimenting with that line, meant to comment it out before posting the code.

    on the stage newsColumn is actually placed inside of the sectionpage movieclip.. does that not mean it's a child of sectionpage?

    This seemed to work before:

    Code:
    sectionpage.newsColumn.addChild(newsPost);

  19. #19
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Then the new columns SHOULD be added to sectionpage. And sectionpage.newsColumn should be put in columns rather than the unused newsColumn property you seem to have declared in NewsPage.

    What line is throwing the 1009 error?

  20. #20
    Member
    Join Date
    Mar 2007
    Posts
    69
    hmm. I dont know, it doesn't say.. it just says:

    Gaia Framework (AS3) v3.2.3
    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at com.thefactory.pages::NewsPage/transitionIn()
    at com.gaiaframework.assets::PageAsset/transitionIn()
    at com.gaiaframework.core::TransitionController/pageIn()
    at com.gaiaframework.core::TransitionController/onTransitionInComplete()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at com.gaiaframework.assets::PageAsset/onTransitionInComplete()
    at com.gaiaframework.assets::PageAsset/transitionIn()
    at com.gaiaframework.core::TransitionController/pageIn()
    at com.gaiaframework.core::TransitionController/onTransitionInComplete()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at com.gaiaframework.assets::PageAsset/onTransitionInComplete()
    at com.gaiaframework.assets::PageAsset/transitionIn()
    at com.gaiaframework.core::TransitionController/pageIn()
    at com.gaiaframework.core::TransitionController/transitionIn()
    at com.gaiaframework.core::SiteController/onTransitionIn()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at com.gaiaframework.core::GaiaHQ/beforeTransitionInDone()
    at com.gaiaframework.core::GaiaHQ/onEvent()
    at com.gaiaframework.core::GaiaHQ/beforeTransitionIn()
    at com.gaiaframework.flow::FlowManager$/transitionIn()
    at com.gaiaframework.flow::NormalFlow$/afterPreloadDone()
    at com.gaiaframework.flow::FlowManager$/afterPreloadDone()
    at com.gaiaframework.core::GaiaHQ/afterPreloadDone()
    at com.gaiaframework.core::GaiaHQ/onEvent()
    at com.gaiaframework.core::GaiaHQ/afterPreload()
    at com.gaiaframework.flow::FlowManager$/preloadComplete()
    at com.gaiaframework.core::SiteController/preloaderEnterFrame()

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center