Working with BlackBerry Layout Managers – Tutorial

Posted October 4th, 2009 by

Introduction

This tutorial will simply walk you through the various layout managers available to you using RIM’s UI API (not MIDP). RIM’s layout managers are akin to Swing layout managers, and allow you to arrange lots of fields (aka components in Swing), on the screen. You can create your own layout managers, just like in Swing, but this tutorial will show you how to use the built in ones. If none of the layout managers shown here work for you, then you can composite layout managers to get the desired look for your app, before creating your own.

To setup the JDE and create a project using it, click here. To setup Eclipse and create a project using it, click here. To learn how to create a skeleton class with a main method, click here.

Layout Managers

There are really just 4 built in layout managers. When you create a layout manager of your choice, you can assign a style to it. These styles are represented by long constants that are defined in the Manager and Field classes. These constants will allow you to set the vertical & horizontal alignment of all fields/components added to a layout manager. You can even set these styles on fields/components that you create to customize how wide or tall they are and what their vertical and horizontal alignment themselves are. These layout managers will handle scrolling for you, so that you don’t have to. This makes it pretty easy to add lots of fields to these managers, and have them handle scrolling for you.

Style attributes

When you set style attributes on fields, which are then added to a layout manager, keep in mind that these style attributes are directives for the layout manager, and not necessarily directives for the field itself. For example, when you specify Field.FIELD_HCENTER as a style parameter for a field, and then add it to a layout manager, this tells the layout manager to try and center the entire field inside of it. If you want to issue style directives that are processed by the field itself (and not the layout manager), then use the DrawStyle style constants/directives. You can issue both types of directives at the same time, here is an example: LabelField lbl = new LabelField(“labeltext”, Field.FIELD_USE_ALL_WIDTH | DrawStyle.HCENTER).

Boxes

Each screen takes up the entire width and height of the display. Inside each screen, is a layout manager (field manager) which handles sizing and positioning field objects that are placed inside of the layout manager (which is inside of the screen, which is is stacked inside of the display). Keep in mind that a manager is also a field, so you can use them interchangeably for layout purposes. Here is a picture that depicts this:

Built in managers

Here are the four layout managers:

  • VerticalFieldManager – this layout manager simply lays out the fields you add to it, from top/bottom. You can control the width and alignment of the fields/components that are added to this layout manager.
  • HorizontalFieldManager – this layout manager simply lays out the fields you add to it, from left to right, on one row. You can control the width and layout of the fields that you add.
  • FlowFieldManager – this layout manager simply adds fields you add from left to right, and adds as many to one row as possible, before starting a new row, and just keeps adding rows as needed. You can control the width and layout of the fields that you add.
  • DialogFieldManager – this layout manager allows you to layout fields in a fixed template, which has an icon and message on the top row, followed by a set of fields you can add underneath it. The fields that you add underneath it are controlled by a simple vertical field manager, but you can nest your own layout manager object here. When scrolling, keep in mind that the entire screen will scroll (it’s not like using setStatus or setTitle on MainScreen).

3rd party layout managers

  • GridFieldManager – this is a nice layout manager that allows you to layout components in the form of a table or grid. It is pretty easy to use and works as one would expect.

The following is a class hierarchy diagram that shows where Manager and it’s subclasses are in the RIM API. If you’re familiar with Swing, then this should be familiar to you. A JComponent is akin to Field, and Managers are very similar to layout managers.

Vertical

Here’s some sample code that shows you how to work with vertical layout manager.

// MAIN CLASS

public class VFMDemo extends UiApplication {
// main method
public static void main(String[] args) {

  VFMDemo theApp = new VFMDemo();
  UiApplication.getUiApplication().pushScreen(new VFMScreen());
  theApp.enterEventDispatcher();

}

..

}

// VFM
public class VFMScreen extends MainScreen {

  public VFMScreen(){

    // create a manager and allow scrolling when lots of fields are added
    VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL);

    // add a label
    vfm.add(new LabelField("VerticalFieldManager..."));

    // add another label
    vfm.add(new LabelField("default horizontal alignment is left"));

    // add another label that takes up full screen width
    vfm.add(new LabelField("using all width & long label...",
                           LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH));

    // add another label that takes centered horizontally
    vfm.add(new LabelField("horizontally centered...",
                           Field.FIELD_HCENTER));

    // add vfm to screen
    add(vfm);

  }

}

Here is a screenshot of what this code produces:

This is what’s going on in the code above:

  1. The VFMDemo class contains the main method that starts this demo app.
  2. In the constructor of VFMScreen, a vertical field manager is created and a style parameter is passed to it, telling it to enable vertical scrolling if lots of fields are added (that don’t fit in the screen).
  3. Then a variety of labels are added to the vertical field manager. A variety of different styles are passed to the constructors of these fields themselves that determine how they are laid out. So you can set styles on the manager as well as the fields to get your desired layout. There’s a lot of trial and error that goes on with this, so test often as you are writing this.
  4. It’s important to note that if a field off the visible area of the screen is not focusable, then scrolling will not work.
  5. Lastly, the vertical field manager is added to the screen. Don’t forget to do this in your code, otherwise you won’t see anything in the UI :) .

Need more help? developerlife.com offers training courses to empower you, and consulting services to enable you.

Scrolling & Focusable

When adding lots of components/fields to the UI, you should keep one thing in mind. The VFM will take care of the vertical scrolling, only if the fields that are off the visible portion of the screen (that the VFM is in) are focusable. If these fields that are off the visible portion of the screen are not focusable, then the VFM will not allow scrolling to them. So when you add a lot of RichTextField objects to a VFM, you should remember to make them FOCUSABLE. Here’s an example – new RichTextField(“Label”, RichTextField.FOCUSABLE | LabelField.ELLIPSIS). So if you find you’ve added a lot of fields to a screen and it’s not scrolling, then chances are some of the fields on it are not focusable.

Horizontal

Here’s some sample code that shows you hw to work with horizontal layout manager.

// MAIN CLASS

public class HFMDemo extends UiApplication {
// main method
public static void main(String[] args) {

  HFMDemo theApp = new HFMDemo();
  UiApplication.getUiApplication().pushScreen(new HFMScreen());
  theApp.enterEventDispatcher();

}

..

}

// HFM
public class HFMScreen extends MainScreen {

  public HFMScreen(){

    // create the layout manager, and enable scrolling...
    HorizontalFieldManager hfm = new HorizontalFieldManager(Manager.HORIZONTAL_SCROLL);

    // if field is not focusable, then scrolling will not work!
    hfm.add(new LabelField("HFM (focusable for scrolling)...",
                            Field.FIELD_VCENTER | Field.FOCUSABLE));

    hfm.add(new LabelField("default VA..."));

    add(hfm);

  }

}

Here is a screenshot of what this code produces:

This is what’s going on in the code above:

  1. The HFMDemo class contains the main method that starts this demo app.
  2. In the constructor of HFMScreen, a horizontal field manager is created and a style parameter is passed to it, telling it to enable horizontal scrolling if lots of fields are added (that don’t fit in the screen). Note that scrolling will happen left and right on the same row, a new row will not be added. So it you add lots of fields, this might look strange in the BB UI.
  3. Then a variety of labels are added to the horizontal field manager. A variety of different styles are passed to the constructors of these fields themselves that determine how they are laid out. So you can set styles on the manager as well as the fields to get your desired layout. There’s a lot of trial and error that goes on with this, so test often as you are writing this.
  4. It’s important to note that if a field off the visible area of the screen is not focusable, then scrolling will not work.
  5. Lastly, the horizontal field manager is added to the screen. Don’t forget to do this in your code, otherwise you won’t see anything in the UI :) .

Flow

Here’s some sample code that shows you hw to work with flow layout manager.

// MAIN CLASS

public class FFMDemo extends UiApplication {
// main method
public static void main(String[] args) {

  FFMDemo theApp = new FFMDemo();
  UiApplication.getUiApplication().pushScreen(new FFMScreen());
  theApp.enterEventDispatcher();

}

..

}

// FFM
public class FFMScreen extends MainScreen {

  public FFMScreen(){

          // default style is Field.USE_ALL_WIDTH | Manager.VERTICAL_SCROLL
          FlowFieldManager ffm = new FlowFieldManager();
                               //new FlowFieldManager(Field.USE_ALL_WIDTH | Manager.VERTICAL_SCROLL | Field.FIELD_VCENTER);

          ffm.add(new LabelField("bla (bottom)...", LabelField.FIELD_BOTTOM));
          ffm.add(new LabelField("bla (top)...", LabelField.FIELD_TOP));

          ffm.add(new BitmapField(..));

          ffm.add(new LabelField("FlowFieldManager (center)...", Field.FIELD_VCENTER));
          ffm.add(new LabelField("default vertical alignment..."));

          add(ffm);

  }

}

Here is a screenshot of what the code produces:

This is what’s going on in the code above:

  1. The FFMDemo class contains the main method that starts this demo app.
  2. In the constructor of FFMScreen, a flow field manager is created, vertical scrolling is enabled by default. You can pass a style parameter to it, telling it to control alignment as shown in the commented code. Note that as you add more fields, they will just be added beside the existing ones, and this will cause more rows and columns to be created.
  3. Then a variety of labels are added to the flow field manager. A variety of different styles are passed to the constructors of these fields themselves that determine how they are laid out. So you can set styles on the manager as well as the fields to get your desired layout. There’s a lot of trial and error that goes on with this, so test often as you are writing this.
  4. You can add any field to this layout manager, like a BitmapField to show an image.
  5. It’s important to note that if a field off the visible area of the screen is not focusable, then scrolling will not work.
  6. Lastly, the flow field manager is added to the screen. Don’t forget to do this in your code, otherwise you won’t see anything in the UI :) .

Dialog

Here’s some sample code that shows you hw to work with flow layout manager.

// MAIN CLASS

public class DFMDemo extends UiApplication {
// main method
public static void main(String[] args) {

  DFMDemo theApp = new DFMDemo();
  UiApplication.getUiApplication().pushScreen(new DFMScreen());
  theApp.enterEventDispatcher();

}

..

}

// DFM
public class DFMScreen extends MainScreen {

  public DFMScreen(){

    DialogFieldManager dfm = new DialogFieldManager();

    dfm.setIcon(new BitmapField(..));
    dfm.setMessage(new RichTextField("Title of DialogFieldManager"));

    dfm.addCustomField(new LabelField("bla (bottom)...", LabelField.FIELD_BOTTOM));
    dfm.addCustomField(new LabelField("bla (top)...", LabelField.FIELD_TOP));
    dfm.addCustomField(new BitmapField(..));
    dfm.addCustomField(new LabelField("bla (center)...", Field.FIELD_VCENTER));
    dfm.addCustomField(new LabelField("default vertical alignment..."));

    add(dfm);

  }

}

Here is a screenshot of what the code produces:

This is what’s going on in the code above:

  1. The DFMDemo class contains the main method that starts this demo app.
  2. In the constructor of DFMScreen, a dialog field manager is created.
  3. Then an icon is set (which goes on the top row). Then a formatted label (RichTextField) is set on the top row as well.
  4. Then a variety of labels are added to the vertical field manager. A variety of different styles are passed to the constructors of these fields themselves that determine how they are laid out. So you can set styles on the manager as well as the fields to get your desired layout. There’s a lot of trial and error that goes on with this, so test often as you are writing this.
  5. It’s important to note that if a field off the visible area of the screen is not focusable, then scrolling will not work.
  6. Lastly, the dialog field manager is added to the screen. Don’t forget to do this in your code, otherwise you won’t see anything in the UI :) .

Grid

Here is some sample code that shows you how to work with grid field manager.

/**
 * GridScreen
 *
 * @author Nazmul Idris
 * @version 1.0
 * @since Dec 12, 2009, 2:45:32 PM
 */

public class GridScreen extends UiApplication {
// main method
public static void main(String[] args) {

  GridScreen theApp = new GridScreen();
  UiApplication.getUiApplication().pushScreen(new GFMScreen());
  theApp.enterEventDispatcher();

}

}

// VFM
class GFMScreen extends MainScreen {

public GFMScreen() {

  // this doesnt do anything for VCENTER!!
  //super(Field.USE_ALL_HEIGHT);

  // create a grid field manager, with 2 cols and 0 style param for super class
  // style of Manager.FIELD_VCENTER | Field.USE_ALL_HEIGHT doesnt do a thing!
  int columns = 2;
  final GridFieldManager gfm = new GridFieldManager(columns, 0);

  // add some items to the screen
  int size = 6;
  BitmapField[] fRay = new BitmapField[size];
  for (int i = 0; i < size; i++) {
    // create an bitmap field that's centered H + V (inside grid space)
    fRay[i] = new BitmapField(loadBitmap("images/" + (i + 1) + ".png"),
                              Field.FIELD_HCENTER | Field.FIELD_VCENTER | Field.FOCUSABLE);
    gfm.add(fRay[i]);
  }

  // set padding on top/bottom
  {
    // add gfm to screen - this does not center the gfm on the screen... is top aligned no matter what!
    add(gfm);

    int gfmHeight = 48 * (size / columns);
    int borderHeight = (Display.getHeight() - gfmHeight) / 2;
    gfm.setBorder(BorderFactory.createSimpleBorder(
        new XYEdges(borderHeight, 0, borderHeight, 0),
        Border.STYLE_TRANSPARENT));

    System.out.println("border=" + borderHeight);
    System.out.println("display=" + Display.getHeight());
    System.out.println("gfm=" + gfmHeight);

  }

}

/** @param res eg "images/icon.png" */
public static Bitmap loadBitmap(String res) {
  EncodedImage img = EncodedImage.getEncodedImageResource(res);
  return img.getBitmap();
}

}// end class

Here is a screenshot of what this code produces:

This is what is going on in the code:

  1. A grid field manager is created with 2 columns.
  2. The items in the grid are centered horizontally using Field.Field_HCENTER.
  3. The grid itself is vertically centered by inserting padding on top of the grid and push the grid down the display so that it looks vertically centered. There is no other easy way to do this.
  4. The images are loaded from the “images/” folder in the JDE, and the filenames are 1.png, 2.png, 3.png, 4.png, 5.png, 6.png
  5. Each BitmapField in the grid is FOCUSABLE, which why the user can select them with the trackwheel, or by touch.

Further reading

RIM has a video that talks about what a UIApplication, screen, fields, and manager is, which is quite informative. Check it out here. This RIM video shows you how to create your own layout managers.


Comments are closed.