How to get a height of Label after Titanium SDK 2? (I can get it before 2)

You must Login before you can answer or comment on any questions.

(i confirms these examples by iOS simulator)

when I use Titanium SDK 1.8.3, i can get a height of Label by the following code.

var label = Ti.UI.createLabel({text: 'fooooo barrrrrr buzzzzzzzz', width: 110, height: 'auto', font: {fontSize: 20}});
win1.add(label);
Ti.API.info(label.height); // 72, OK
Ti.API.info(label.toImage().height); // 72, OK
but, after 2, i can't get it. i tried the following code on 2.0.2 GA, 2.1.0 GA, 2.1.1 GA and it didn't work.
var label = Ti.UI.createLabel({text: 'fooooo barrrrrr buzzzzzzzz', width: 110, height: 'auto', font: {fontSize: 20}});
win1.add(label);
Ti.API.info(label.height); // 'auto'
Ti.API.info(label.toImage().height); // 24 ... it maybe a height of only one line
label.addEventListener('postlayout', function(e) { // not called ...
  Ti.API.info(e.source.rect.height);
});
how can i do that? thanks in advance.

— asked 10 months ago by Takumi Tsunokake
3 Comments
  • i referred this page to code. http://developer.appcelerator.com/question/139552/how-to-get-label-height-

    — commented 10 months ago by Takumi Tsunokake

  • EDIT 2: after 2, i also tried to change the height argument of label, e.g. 'auto', Ti.UI.SIZE, Ti.UI.FULL, but i can't get it

    — commented 10 months ago by Takumi Tsunokake

  • EDIT 3: i really want to do is that "for example, i'd like to create a TableViewRow which has two flexible-height labels. so i have to adjust a height of TableViewRow depending on these labels. i tried to code as follows, but it didn't go well."

    — commented 10 months ago by Takumi Tsunokake

4 Answers

Accepted Answer

Hi Takumi

This code will create a new row, with a title and an optional subtitle, both can be whatever length of text you like and they will automatically size themselves as required within the row - which will also automatically resize itself to fit the contents.

You would need to tweak it to suit your visual needs, but functionally it does everything you want without ANY need to calculate ANY dimensions manually.

Fully tested on iOS and Android, plus I have made it as a function that you can call as option as you like in a loop.

function addRow(obj) {  
    Ti.API.info('title', obj.title);
    Ti.API.info('subtitle', obj.subtitle);
    var row = Ti.UI.createTableViewRow({
        height: Ti.UI.SIZE,
        backgroundColor: '#fff',
        width: Ti.UI.FILL
    });
    var viewParent = Ti.UI.createView({
        bottom: 10, // use as margin from the row edges
        height: Ti.UI.SIZE,
        layout: 'vertical',
        left: 10, // use as margin from the row edges
        right: 10, // use as margin from the row edges
        top: 10, // use as margin from the row edges
        width: Ti.UI.FILL    
    });
    row.add(viewParent);
    var lblTitle = Ti.UI.createLabel({
        font: {
            fontSize: 20
        },
        height: Ti.UI.SIZE,
        left: 0,
        text: (obj.title || ''),
        width: Ti.UI.SIZE
    });
    viewParent.add(lblTitle);
    if (obj.subtitle) {
        var lblSubTitle = Ti.UI.createLabel({
            color: '#666', // used for contrast only
            font: {
                fontSize: 20
            },
            height: Ti.UI.SIZE,
            left: 0,
            text: (obj.subtitle || ''),
            top: 10, // this will place 10 pixels between the title and the subtitle - adjust to suit your needs
            width: Ti.UI.SIZE
        });
        viewParent.add(lblSubTitle);
    }
    return row;
}
 
var data = [];
 
data.push(addRow({
    title: 'Title 1',
    subtitle: 'Sub-title 1'
}));
data.push(addRow({
    title: 'Title 2'
}));
data.push(addRow({
    title: 'Title 3',
    subtitle: 'Sub-title 3 is really long and with any luck will jump across more than one line within the row.'
}));
 
var tbl = Ti.UI.createTableView({
    height: Ti.UI.FILL,
    data: data,
    width: Ti.UI.FILL
});
 
win.add(tbl);

Hi Takumi

This has actually become much easier and much more efficient of resources.

Use the new function getRect(). For example;

Ti.API.info(label.getRect().height);
See this documentation

— answered 10 months ago by Malcolm Hollingsworth
answer permalink
4 Comments
  • It wont work until the layout is finished. This is also documented in your link, to quote

    The correct values will only be available when layout is complete.

    — commented 10 months ago by Alexander Bauer

  • Wow you jumped in quick with a minus one, I was just adding to this.

    — commented 10 months ago by Malcolm Hollingsworth

  • Sorry for that but you should put it in your answer, instead of after-commenting it.

    — commented 10 months ago by Alexander Bauer

  • Show 1 more comment

label.addEventListener('postlayout', function(e) { // not called ...
  Ti.API.info(e.source.rect.height);
});
Is the correct one, you need to remove toImage() or call it after postlayout.

— answered 10 months ago by Alexander Bauer
answer permalink
7 Comments
  • hi Alexander,

    thanks for your comment ;)

    i tried it, then,

    var label = Ti.UI.createLabel({text: 'fooooo barrrrrr buzzzzzzzz', width: 110, height: 'auto', font: {fontSize: 20}});
    win1.add(label);
    label.addEventListener('postlayout', function(e) {
      Ti.API.info(e.source.rect.height); // 0, NG
    });
    var label = Ti.UI.createLabel({text: 'fooooo barrrrrr buzzzzzzzz', width: 110, height: 'auto', font: {fontSize: 20}});
    win1.add(label);
    label.addEventListener('postlayout', function(e) {
      Ti.API.info(e.source.getRect().height); // 0, NG
    });
    var label = Ti.UI.createLabel({text: 'fooooo barrrrrr buzzzzzzzz', width: 110, height: 'auto', font: {fontSize: 20}});
    win1.add(label);
    label.addEventListener('postlayout', function(e) {
      Ti.API.info(e.source.toImage().height); // 72, OK
    });
    i don't understand what it goes but getRect() and rect return correct height after toImage().
    var label = Ti.UI.createLabel({text: 'fooooo barrrrrr buzzzzzzzz', width: 110, height: 'auto', font: {fontSize: 20}});
    win1.add(label);
    label.addEventListener('postlayout', function(e) {
      Ti.API.info(e.source.toImage().height); // 72, OK
      Ti.API.info(e.source.getRect().height); // 72, OK
      Ti.API.info(e.source.rect.height); // 72, OK
    });

    — commented 10 months ago by Takumi Tsunokake

  • Well its because you add the label to the window and then you add the eventListener, so basically the event is called before you even had a chance to add a listener to it.

    You should always add the eventListener first and then add the element to a container such as a window.

    — commented 10 months ago by Alexander Bauer

  • the above result is 2.1.1 GA

    — commented 10 months ago by Takumi Tsunokake

  • Show 4 more comments

Hi Takumi

The problem might relate to the fact you have more than just a label on the window and because of this other views updates are effecting your label and how it reports back.

Try moving the postlayout event to the parent, or even the window.

win1.addEventListener('postlayout', function(e) {
  Ti.API.info(label.getRect().height);
});
Chances are this may fire more than once, but the answer should be right.

You can reduce the number of times it fires by adding this at the start

win1.startLayout();
and this at the end.
win1.finishLayout();

— answered 10 months ago by Malcolm Hollingsworth
answer permalink
3 Comments
  • hi, Malcolm, thanks for your kind answer :)

    yes, that is i really want to do. for example, i'd like to create a TableViewRow which has two flexible-height labels. so i have to adjust a height of TableViewRow depending on these labels. i tried to code as follows, but it didn't go well.

    var win = Ti.UI.createWindow({backgroundColor: 'white'});
    var tableView = Ti.UI.createTableView();
    var row = Ti.UI.createTableViewRow();
     
    var label1 = Ti.UI.createLabel({
      text: 'fooooo baaaaaaaar buzzzzzzz',
      top: 0,
      width: 110,
      height: 'auto',
      font: {fontSize: 20}
    });
     
    var label2 = Ti.UI.createLabel({
      text: 'hello woooorld',
      width: 110,
      height: 'auto',
      font: {fontSize: 20}
    });
     
    row.addEventListener('postlayout', function(e) {
      Ti.API.info(label1.rect.height); //=> 72
      Ti.API.info(label2.rect.height); //=> 48
     
      label2.top = label1.rect.height + 5; 
     
      row.height = label1.rect.height + label2.rect.height + 5; // it makes loop..
    });
    row.add(label1);
    row.add(label2);
     
    tableView.data = [row];
     
    win.add(tableView);
    win.open();
    UI seems to be good, but it has a infinite loop. how can i do that?

    — commented 10 months ago by Takumi Tsunokake

  • Hi

    Do you want them above each other or side by side?

    Let me know and I will give you the answer right back.

    — commented 10 months ago by Malcolm Hollingsworth

  • thanks ;) i'd like to align vertically each label, not horizontally.

    — commented 10 months ago by Takumi Tsunokake

Your Answer

Think you can help? Login to answer this question!