canvas
Using bitmap fonts
With this example we are going to demonstrate how to use bitmap fonts in an Android Application. Android is running on a wide variety of devices with lots of different screen sizes and resolutions.
So bitmap fonts can help you address the problem of using a consistent font face across different devices. For this tutorial we are going to use a monospaced font alphabet which means that all the characters have the same width and height.
In short, to create and use bitmap fonts you should:
- create an image containing all the characters of the alphabet you want, with transparent background and copy it to a drawable Android resource foulders
- measure the height and the width of a sample character on your image, in pixels
- create a bitmap containing the character map
- assosiate all the characters and numbers of the alphabet with a substet bitmap, derived from the main bitmap
- use Glyphs an canvans to draw the sting you want on the screen
as shown in the code snippets below:
package net.obviam.fonts;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = DrawingPanel.class.getSimpleName();
private Canvas canvas; // the canvas to draw on
private Glyphs glyphs; // the glyphs
public DrawingPanel(Context context) {
super(context);
// adding the panel to handle events
getHolder().addCallback(this);
// initialise resources
loadResources();
// making the Panel focusable so it can handle events
setFocusable(true);
}
/**
* Loads the images
*/
private void loadResources() {
this.glyphs = new Glyphs(BitmapFactory.decodeResource(getResources(), R.drawable.glyphs_green));
Log.d(TAG, "Green glyphs loaded");
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// draw text at touch
try {
canvas = getHolder().lockCanvas();
synchronized (getHolder()) {
if (event.getAction() == MotionEvent.ACTION_DOWN
|| event.getAction() == MotionEvent.ACTION_MOVE) {
// clear the screen
canvas.drawColor(Color.BLACK);
// draw glyphs
glyphs.drawString(canvas, "Drawing string at "
+ (int) event.getX() + " " + (int) event.getY(),
(int) event.getX(), (int) event.getY());
}
if (event.getAction() == MotionEvent.ACTION_UP) {
canvas.drawColor(Color.BLACK);
glyphs.drawString(canvas, "Drawn string at "
+ (int) event.getX() + " " + (int) event.getY(),
(int) event.getX(), (int) event.getY());
}
}
} finally {
if (canvas != null) {
getHolder().unlockCanvasAndPost(canvas);
}
}
// event was handled
return true;
}
@Override
protected void onDraw(Canvas canvas) {
}
}package net.obviam.fonts;
import java.util.HashMap;
import java.util.Map;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
public class Glyphs {
private static final String TAG = Glyphs.class.getSimpleName();
private Bitmap bitmap; // bitmap containing the character map/sheet
// Map to associate a bitmap to each character
private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>(62);
private int width; // width in pixels of one character
private int height; // height in pixels of one character
// the characters in the English alphabet
private char[] charactersL = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z' };
private char[] charactersU = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z' };
private char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7',
'8', '9', '0' };
public Glyphs(Bitmap bitmap) {
super();
this.bitmap = bitmap;
this.width = 8;
this.height = 12;
// Cutting up the glyphs
// Starting with the first row - lower cases
for (int i = 0; i < 26; i++) {
glyphs.put(charactersL[i], Bitmap.createBitmap(bitmap,
0 + (i * width), 0, width, height));
}
Log.d(TAG, "Lowercases initialised");
// Continuing with the second row - upper cases
// Note that the row starts at 15px - hardcoded
for (int i = 0; i < 26; i++) {
glyphs.put(charactersU[i], Bitmap.createBitmap(bitmap,
0 + (i * width), 15, width, height));
}
// row 3 for numbers
Log.d(TAG, "Uppercases initialised");
for (int i = 0; i < 10; i++) {
glyphs.put(numbers[i], Bitmap.createBitmap(bitmap,
0 + (i * width), 30, width, height));
}
Log.d(TAG, "Numbers initialised");
// TODO - 4th row for punctuation
}
public Bitmap getBitmap() {
return bitmap;
}
/**
* Draws the string onto the canvas at <code>x</code> and <code>y</code>
* @param text
*/
public void drawString(Canvas canvas, String text, int x, int y) {
if (canvas == null) {
Log.d(TAG, "Canvas is null");
}
for (int i = 0; i < text.length(); i++) {
Character ch = text.charAt(i);
if (glyphs.get(ch) != null) {
canvas.drawBitmap(glyphs.get(ch), x + (i * width), y, null);
}
}
}
}package net.obviam.fonts;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
public class PrintingActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// turn off title
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new DrawingPanel(this));
}
}
This was an example of how to Use Bitmap Fonts in Android.
Related Article:
Reference: Using Bitmap Fonts in Android from our JCG partner Tamas Jano at the “Against The Grain” blog.

