Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Fonts

You can apply different fonts to the text in your applications. A font is represented by the Font class, which is included in the net.rim.device.api.ui package. Each font has a style that is specified by using the style bits that are defined in the Font class, such as Font.BOLD, Font.ITALIC, and Font.PLAIN. Each font also has a size, which refers to the height of the font in a particular unit of measurement (points, millimeters, or pixels). A Font object cannot be altered after it is created, so you can use a reference to a Font object and be sure that the font that it refers to always has the same style and size. To set the font for a field, you can invoke Field.setFont(Font).

You can use methods of the Font class to retrieve various font properties. You can invoke getHeight() to retrieve the height of the font (in pixels), which can be useful if you create a custom field and need to implement Field.layout() to place text in a field's content area. You can also invoke isBold(), isItalic(), isUnderlined(), and isPlain() to determine the style of the font. If you want to retrieve the default font that is currently set on the BlackBerry device, you can invoke the static Font.getDefault().

To create Font objects that you can apply to text, you can use the FontFamily class. A font family is a collection of fonts of differing sizes and styles that belong to the same typeface and use the same font family name. For example, BBAlpha Sans and Times New Roman are two font families that are available in the BlackBerry Java SDK.

You can use FontFamily as a factory to create Font objects that have specific styles and sizes. You can invoke the static FontFamily.forName(String), which returns a FontFamily object that corresponds to the font family name that you specify. For example, the following code sample retrieves a FontFamily object that corresponds to the BBMillbank font family:

try
{
    FontFamily fontFam = FontFamily.forName("BBMillbank");
}
catch (ClassNotFoundException e)
{
    System.out.println("The specified font family was not found.");
}

The FontFamily.forName(String) method throws a ClassNotFoundException if the specified font family is not registered on the device, so it's important to catch this exception when you try to retrieve a FontFamily object using this method. You can retrieve a list of all font families that are registered on the device by invoking the static FontFamily.getFontFamilies().

After you retrieve a FontFamily, you can invoke getFont(int, int) to retrieve a Font object with the specified style and size that is part of that font family. For example, if fontFam is a FontFamily object that represents the BBMillbank font family, then you can invoke fontFam.getFont(Font.BOLD, 18) to retrieve a Font object of this font family with a bold style and a height of 18 pixels.

Measuring text

In your BlackBerry device applications, you might need to measure the space that a character or string of characters occupies on the screen. For example, if you create a custom field that contains text, you might need to know the width of the text so that you can draw the field with the proper size. You can use methods of the Font class to measure text.

There are three methods that you can use to measure text:

  • getAdvance()
  • getBounds()
  • measureText()

Each of these methods is overloaded to accept various sets of parameters. For example, these methods can accept a single character, character array, String object, or StringBuffer object to measure, and can also accept a starting offset and length of the text to measure.

The getAdvance() method retrieves the advance width of the specified text. The advance width is defined as the distance from the origin of the text to the starting position of the character that is drawn immediately after the text. Depending on the font family and style of the text, the advance width might not represent the entire space that is required to draw the text. For example, text that uses italic style is typically slanted to the right, meaning that the top of a character in a string of italic text is positioned further to the right than the bottom of that character. The advance width of this text is the distance from the origin of the text to the bottom of the last character. This measurement might not be sufficient to draw the text properly, because it does not include the full extent of the text.

How a font may extend past the advanced width.

The getBounds() method retrieves the full width of the specified text. You can use this method to retrieve the entire horizontal width that is required to draw the text. For example, if you use this method to retrieve the width of italic text, you will receive the distance from the origin of the text to the top of the last character. This method is typically the most useful method to use when you need to measure text in your applications.

Capturing the full width of the text.

The measureText() method retrieves the advance width of the specified text, but can also accept parameters that control the way that the measurement is performed. You can also specify the properties that you want to receive from the measurement.

To avoid unnecessary calculations in your application, you should measure text as infrequently as possible. You might choose to measure text in layout() or paint(), but these methods are invoked frequently and so the measurements would be performed more often than necessary. Instead, you should override applyFont() and measure text in this method. The applyFont() method is invoked when you create a screen, and is also invoked if the BlackBerry device user changes the system font while your application is running.

public void applyFont()
{
    // Measure your text here
}

Code sample: Using fonts in your application

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.container.MainScreen;

import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.FontFamily;
import net.rim.device.api.ui.component.LabelField;


public class FontDemo extends UiApplication
{
    public static void main(String[] args)
    {
        FontDemo theApp = new FontDemo();       
        theApp.enterEventDispatcher();
    }
    
    public FontDemo()
    {
        pushScreen(new FontDemoScreen());
    }    
}

public class FontDemoScreen extends MainScreen
{
    public FontDemoScreen()
    {
        setTitle("Font Demo");
        
//In the screen constructor, create a LabelField object with the 
//text that you want to apply a font to.
        LabelField firstFontLabel = new 
            LabelField("This text uses the BBMillbank font, size 18, plain style.");
        LabelField secondFontLabel = new
            LabelField("This text uses the Comic Sans MS font, size 24, italic style.");
        LabelField thirdFontLabel = new
            LabelField("This text uses the Times New Roman font, size 32, bold style.");
       
//In a try/catch block, do the following: 
//Create a FontFamily object to represent the font family that you want to apply to your
//text. Create a Font object that uses the font family and has a specific style and size.
//Apply the font to the LabelField object that you created. 
        try
        {
            FontFamily firstFF = FontFamily.forName("BBMillbank");
        	   Font firstFont = firstFF.getFont(Font.PLAIN, 18);
        	   firstFontLabel.setFont(firstFont);
        	
        	   FontFamily secondFF = FontFamily.forName("Comic Sans MS");
        	   Font secondFont = secondFF.getFont(Font.ITALIC, 24);
        	   secondFontLabel.setFont(secondFont);
        	
        	   FontFamily thirdFF = FontFamily.forName("Times New Roman");
        	   Font thirdFont = thirdFF.getFont(Font.BOLD, 32);
        	   thirdFontLabel.setFont(thirdFont);
        }
//Catch a ClassNotFoundException, which indicates that the font family that you specified 
//in FontFamily.forName() is not registered on the BlackBerry device.
        catch (ClassNotFoundException e)
        {
        	   System.out.println(e.getMessage());
        }
        
//Add the LabelField object to the screen.
        add(firstFontLabel);
        add(secondFontLabel);
        add(thirdFontLabel);
    }
}

Deriving fonts

You can derive fonts to create new fonts to use in your applications. When you derive a font, the new font has the same font family as the original font but you can specify different values for other properties. For example, you can derive a new font that has a different style, height, or advanced properties (such as anti-alias mode or visual effects) than the original font. You can use derive() of the Font class to derive a font. This method is overloaded to accept various sets of parameters that correspond to the properties of the font that you want to change.

You can derive fonts in several methods in your application, including paint() and layout(). The paint() method is invoked many times while your application runs, such as when the screen scrolls or the focus area changes, and it is not likely that you need to derive a new font each time one of these events occurs. The layout() method is invoked when you add or remove fields on a screen, or when the BlackBerry device is rotated, so you might choose to measure text in this method and cache the values to use in paint().

You can also override applyFont() and derive fonts in this method. When a screen is created, applyFont() is invoked on all fields of the screen. This method call occurs before the first layout() call and before the first paint() call. Because applyFont() is invoked much less frequently than layout() and paint(), you should derive fonts in applyFont() whenever possible.

When you derive a font, you should consider deriving from the default system font on the device, which you can retrieve by invoking the static Font.getDefault(). By using this approach, you can make sure that the text in your application fits thematically with the text in other applications on the device. If you choose to use derive from the system font, you should consider deriving the new font height as a proportion of the system font height. If the BlackBerry device user changes the size of the system font, your derived font is resized accordingly.

Code sample: Deriving a font

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.container.MainScreen;

import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.component.LabelField;

public class DerivingFontDemo extends UiApplication
{
    public static void main(String[] args)
    {
        DerivingFontDemo theApp = new DerivingFontDemo();       
        theApp.enterEventDispatcher();
    }

    public DerivingFontDemo()
    {        
        pushScreen(new DerivingFontDemoScreen());
    }    
}

public class DerivingFontDemoScreen extends MainScreen
{
    public DerivingFontDemoScreen()
    {          
        setTitle("Deriving Font Demo");

//In the screen constructor, create a LabelField object with the text that 
//you want to apply a font to.
        LabelField defaultFontLabel = new
            LabelField("This font is the current default font on the BlackBerry device.");
        LabelField secondFontLabel = new
            LabelField("This font is derived from the default font and is 50% larger.");
        LabelField thirdFontLabel = new
            LabelField("This font is derived from the default font and is underlined.");
  
//Create a Font object to represent the font that you want to derive from. In this 
//code sample, that font is the default system font on the BlackBerry device.      
        Font defaultFont = Font.getDefault();
        
//Derive a font with the properties that you want.
        Font secondFont = defaultFont.derive(Font.PLAIN, defaultFont.getHeight() * 3 / 2);
        Font thirdFont = defaultFont.derive(Font.UNDERLINED, defaultFont.getHeight());
        
//Apply the font to the LabelField object that you created.
        secondFontLabel.setFont(secondFont);
        thirdFontLabel.setFont(thirdFont);
       
//Add the LabelField object to the screen. 
        add(defaultFontLabel);
        add(secondFontLabel);
        add(thirdFontLabel);        
    }
}

Custom fonts

The FontManager class in the net.rim.device.api.ui package provides constants and methods that you can use to install and uninstall a TrueType font on a BlackBerry device. The maximum size allowed for the TrueType font file is 60 KB. You can specify whether the font is available to the application that installs the font or to all applications on the BlackBerry device.

The FontManager class also provides methods to set the default font for the BlackBerry device or application.

Code sample: Installing and using a custom font in a BlackBerry Java application

import net.rim.device.api.system.*;
import net.rim.device.api.ui.*; 
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.component.*;
import java.util.*;

//Create the application framework by extending the 
//UiApplication class. In main(), create an instance of the 
//new class and invoke enterEventDispatcher() to enable the 
//application to receive events. In the application constructor, 
//invoke pushScreen() to display the custom screen for the
//application.
public class FontLoadingDemo extends UiApplication
{
    public static void main(String[] args)
    {
        FontLoadingDemo app = new FontLoadingDemo();
        app.enterEventDispatcher();
    }
    
    public FontLoadingDemo()
    {
        pushScreen(new FontLoadingDemoScreen());
    }
}

//Create the custom screen by extending the MainScreen class. Invoke 
//setTitle() to set the text that appears in the title section of the 
//screen. Create a new LabelField object. You will apply the custom font to
//this object.
class FontLoadingDemoScreen extends MainScreen
{	
    public FontLoadingDemoScreen()
    {
        setTitle("Font Loading Demo");

        LabelField helloWorld = new LabelField("Hello World");
        
//In the screen constructor, invoke the FontManager.getInstance() method to 
//get a reference to the FontManager object, then invoke the load() method to 
//install the font. Wrap the load() invocation in an IF statement to check if 
//the installation was successful. The load() method returns a flag specifying 
//if font is successfully installed. The following code specifies that the font 
//that can be used only by the application.
        if (FontManager.getInstance().load("Myfont.ttf",
              "MyFont", FontManager.APPLICATION_FONT) == FontManager.SUCCESS) 
        {

//In the screen constructor, in a try/catch block in the IF
//statement, create a Font object for the font you just installed. 
//Invoke the setFont() method to apply the font to the LabelField you created.
            try 
            {
                FontFamily typeface = FontFamily.forName("MyFont");
                Font myFont = typeface.getFont(Font.PLAIN, 50);
                helloWorld.setFont(myFont); 
            }
            catch (ClassNotFoundException e) 
            {
                System.out.println(e.getMessage());
            }
        }

//In the screen constructor, invoke add() to add the LabelField to the screen.
        add(helloWorld);
    }
}