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:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 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) { } } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 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 ); } } } } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | 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.