Do automatically scaling font sizes work for android, using appcelerator?
Asked Answered
M

4

8

Just trying to get clarification on this issue. Is the scaling of fonts working for android using this attribute? Its working for iOS, I know, but it doesn't seem to want to play nice for android.

I'm trying to make a label that has a string of varying size in it. Here is a sample of the code that I'm using:

var name = Titanium.UI.createLabel({ text:response.name, color:'#000', minimumFontSize:10, font:{fontSize:24,fontFamily:'Helvetica Neue'}, width:120, height:45, top:0, left:0, right:2, wordWrap:false, textAlign:'left' });
Maecenas answered 16/12, 2011 at 22:4 Comment(1)
+1 for your question. The docs at docs.appcelerator.com/titanium/2.1/index.html#!/api/Font mention that Titanium on Android will support px, pt, dp, mm and in, but they do not mention sp.Trice
H
3

Use 'sp' as measurement unit for font and 'dp' for sizes (example: fontSize: '24sp'). You can read more about density-specific resources on Android here.

Hying answered 14/2, 2012 at 16:10 Comment(2)
SteelRat, thanks for referring to what Android supports. But just because Android has dp and sp doesn't mean that both are supported by Titanium. Do you have any more definite knowledge about this?Trice
@Wytze, I have tested 'sp' and it works for me. Here is similiar question on appcelerator Q&A service - developer.appcelerator.com/question/130143/….Hying
K
0

If you are asking about whether 'minimumFontSize' on a label works on Android to automatically scale the size of the text to fit the label on a single line, according to the latest documentation for Titanium 3.X here:

http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.UI.Label-property-minimumFontSize

no, it only works on iPhone and iPad

Kavita answered 14/7, 2013 at 6:9 Comment(0)
O
0

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.

Oppose answered 23/5, 2014 at 11:26 Comment(0)
D
0

This parity-feature (TIMOB-1618) is currently in review and will be available in Titanium SDK 6.1.0 and later. The parity-review took some time, but you can already grab the changes from this Pull Request and apply them to your SDK today.

Durham answered 30/12, 2016 at 11:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.