This might be a bit off topic, but this is the code we use to make sure some text fits a label. You call the function in a postLayout event handler or at some other moment when the dimensions of the label and the screen are known.
function fitTextInLabel(label,options)
{
/*
* Make the given text fit in the label by, well, just trying. Run this when the layout is complete
* IE in the onPostlayout of the view or the label. When using the cache-feature don't forget to
* check for orientation in creating the cache key: otherwise the font size will not be recalculated for the other orientation
* This is an alloy function: it requires underscore.js But rewriting it for plain titanium is not a big deal.
* Spin in het Web - www.spininhetweb.nl - Contact us for questions. Yes we build apps.
*
* Label: the Ti.UI.Label to fit the text in
* Options: an options object:
* text: the text to fit. When not given we will use the current text of the label. Use a lorum ipsum that's big enough.
* fitWidth: which width to fit the text in. Either the fixed width of the label ("current") or that of the parent ("parent"). When
* width is Ti.UI.SIZE use "parent". Default: current.
* fitHeight: which height to fit the text in. "current" or "parent". Default: current
* marginVertical: space to keep vertically. Will use marginVertical / 2 for top and bottom. Default: 0
* marginHorizontal: space to keep horizontally. Will use marginHorizontal / 2 for left and right. Default: 0
* cacheKey: string. When given, use caching. We will save the found fontsize as a persistant property. When called again with the same key
* we will not calculute, but just set the fontsize. The cache is only cleared when the user removes the app or its data
* We add the device orientation to the cacheKey, so we automatically differentiate between setting for portrait and landscape
* applyTo: array of labels. When given, we will set the same fontsize on the given labels.
* callback: function. When given, we will call this after setting the fontsize on the label. The prototype for the callback function is:
* fn(Ti.UI.Label lbl, int newFontSize)
*
* RETURNS boolean. False on some error, true when everything started out okay.
*
* This function runs on the event engine so it is basically async. After calling it, the font will not be changed until the callback runs
*/
//defaults
var o =
{
text: false,
fitWidth: "current",
fitHeight: "current",
marginVertical: 0,
marginHorizontal: 0,
cacheKey: false,
deleteCache: false, //special for development: set to true to recache without using the old value
callback: false,
applyTo: []
};
if (typeof(options) == "object")
{
_.each(options, function(v,k)
{
o[k] = v;
});
}
//o now contains all the chosen options plus defaults for the rest
//add orientation to the cachekey
if (o.cacheKey)
{
o.cacheKey = o.cacheKey + "_" + Ti.Gesture.orientation; //int
}
//log("*** fitTextInLabel label " + label.id + " tekst " + (o.text ? o.text : "(origineel)"),o);
var font = _.clone(label.font);
//cache?
if (o.cacheKey && (! o.deleteCache))
{
var cached = Ti.App.Properties.getInt(o.cacheKey,0);
if (cached)
{
font.fontSize = cached;
label.setFont(font);
//log("*** Cached op key " + o.cacheKey + " fontSize: " + cached);
_.each(o.applyTo,function(otherlabel)
{
//just set the font
var f = otherlabel.font;
f.fontSize = cached;
otherlabel.setFont(f);
});
//callback
if (o.callback)
{
o.callback(label,cached);
}
return; //done
}
}
//find the fontsize that fits in the label
//we use a different label outside of the view, to check it
var labelsize = label.getSize();
var parentsize = label.parent.getSize();
//which width and height to use?
var maxw = (o.fitWidth == "parent" ? parentsize : labelsize).width - (o.marginHorizontal / 2);
var maxh = (o.fitHeight == "parent" ? parentsize : labelsize).height - (o.marginVertical / 2);
//log("*** Moet passen in " + maxw + " X " + maxh);
font.fontSize = 40; //beginnen we mee, kan hoger en lager
var starting = true; //voor als we omhoog moeten
//create the test label in the parent container, using a postLayout callback for checking the fit
var testl = Ti.UI.createLabel({
text: (o.text ? o.text : label.getText()),
width: label.wordWrap ? maxw : Ti.UI.SIZE, //when wrapping, use a fixed with, otherwise just see how big it becomes
height: Ti.UI.SIZE, //we want to measure the height after setting the font size
wordWrap: label.wordWrap, //copy the wordWrap from the real label
font: font,
top: -5000 //somewhere out of view please (does this create scrollbars?)
});
var done = false;
var onPostLayout =
function()
{
//called when the test label is relayout because of the font change, so let's see how it all fits now
if (done)
{
return;
}
var lsize = testl.getSize();
//log("*** Proberen " + font.fontSize,lsize);
//We declare it a fit when the font becomes to small, fits inside the height of a wrapping label
//or fits inside the height AND width of a nonwrapping label
if (font.fontSize == 5 || (lsize.height <= maxh && (label.wordWrap || lsize.width < maxw)))
{
//it fits!
//did we startup with a too small font?
if (starting)
{
//the fontsize we started with fits. So let's try something bigger
font.fontSize += 10;
testl.setFont(font);
}
else
{
//we found it: it fits the space or is so small we stop trying
//log("*** Past!");
done = true; //stop the postLayout eventloop
label.setFont(font); //set the font
testl.parent.remove(testl);
testl = null; //garbace collect
if (o.cacheKey)
{
//let's cache this value
//log("*** Cachen naar " + o.cacheKey + ": " + font.fontSize);
Ti.App.Properties.setInt(o.cacheKey,font.fontSize);
}
//set the font for the applyTo array
_.each(o.applyTo,function(otherlabel)
{
//just set the font
var f = otherlabel.font;
f.fontSize = font.fontSize;
otherlabel.setFont(f);
});
//and callback
if (o.callback)
{
o.callback(label,font.fontSize);
}
}
}
else
{
//no fit yet. Let's try a pixel smaller
font.fontSize--;
testl.setFont(font); //this will fire a new postLayout event, running this function again
starting = false; //we are no longer starting up. When we find a fit, it's what we'll use
}
};
//let's go
testl.addEventListener("postlayout",onPostLayout);
label.parent.add(testl);
return true;
}
Hope this helps someone.