Most BlackBerry® device applications begin by pushing a MainScreen or an extension of one onto the screen stack. However, you might not realize that in MainScreen you have a very fine instrument which can easily bite you in the back if you are not careful. It also has a few problems I want to discuss as well.
So, what can a MainScreen do for you? It pre-populates the menu with the system items - "Switch application" and "Close". It reacts to "Escape" key by checking whether anything on the screen need saving ("dirty" fields), then closing (popping) itself, and, if it is the last screen on the stack, exiting the application. But that is far from all it can do.
Banner / Title / Status areas
One of the very useful possibilities provided by MainScreen is the ability to add two non-scrolling ("docked") areas to the otherwise scrolling screen.
Banner & Title
Banner and Title both reside at the top of the screen.
You create a banner using MainScreen.setBanner(Field banner) method. Since a Manager is also a Field, you can create quite a sophisticated banner this way.
The main idea behind the banner is to provide a universal top area which contains some constant items you always want to show - your company's logo and name, your application name, quick links to the most frequently used parts of your application, etc.
Title also sits on top of the screen, just below the banner (if present).
You create a title using either MainScreen.setTitle(String title) or MainScreen.setTitle(Field title). Logically, title is used for the name of the current application "screen" - "Reports", "Your order", "Our School Soccer Team - Season 2010-2011", etc.
Interestingly enough, title has a different theme: by default, fields in title have black background and white foreground. Even if you override the colors in the Field you set as title, the title Manager (invisible by your code but present) has a bottom padding of 2 (checked on a 9700 simulator - portrait and lower resolution screens might have different values), making sure that you always get at least a thin black line on top of the main area.
If you don't like this "theme" approach, utilize banner for both your banner and title needs. A VerticalFieldManager looks like a good container for your banner+title in this case.
Status is located at the bottom of the screen and is also always visible regardless of the main area scrolling position.
You create a status using MainScreen.setStatus(Field status). As usual, Manager is a Field, so you can have some sophisticated logic there. Some applications use status for messages ("Loading http://...", "Loading images - 13 of 15 completed", etc.), others - for buttons ("Submit order", "Cancel") and so on.
The main area is managed by a VerticalFieldManager which gets most style bits from the MainScreen. This Manager is accessible via getMainManager(), and it is the one who becomes a parent of fields "added" to the MainScreen via its Screen.add(Field field) method. By default, the main manager is created with VERTICAL_SCROLL and VERTICAL_SCROLLBAR style bits.
All of the above can be illustrated by the following screenshots (notice the "scrollbar" triangles)
Figure 1: MainScreen with focus on the banner:
Figure 2: MainScreen with focus in the main area, partially scrolled:
Figure 3: MainScreen with focus in the status area:
MainScreen - using style bits for customization
You might have noticed that I've emphasized the fact that by default the main area of a MainScreen is scrollable and displays a scrollbar. Why is it important?
Some applications want a very fine control over the screen. Developers achieve this by creating their own custom managers which usually have USE_ALL_HEIGHT and USE_ALL_WIDTH style bits (or the equivalent setExtent() in their custom sublayout() methods). Added to a FullScreen, such a custom manager will get the full screen dimensions. This is one of the ways to determine display size without using the signature-requiring Display.getWidth() and Display.getHeight() methods. It also lets the developers to decide whether their manager should be scrolling and manage that scroll internally - say, display a nice-looking scrollbar (see this knowledge base article for example). Developers of such applications usually add their custom Manager to the MainScreen and the rest of the fields to display to that Manager. This also applies to the workaround needed to add a background image to the MainScreen - see below.
However, added to a default MainScreen, such a manager will get the height of ... 0x3FFFFFFF (Integer.MAX_VALUE >> 1)! It happens because a VerticalFieldManager created with VERTICAL_SCROLL style bit lets its children have a virtually unlimited height. In order to prevent this we need to create our MainScreen differently.
So, how do we overcome the MainScreen being too helpful without discarding its other nice features?
For those applications which use MainScreen directly, replace your
pieces of code with
Those classes which extend MainScreen will need to add
as the first line of their constructors.
This NO_VERTICAL_SCROLL exercise hopefully raised your awareness of MainScreen(long style) constructor availability. Now that you know it's there you may play with different style bits, see which ones make sense and use them to enhance and beautify your application.
In addition to providing you with default menu items, MainScreen allows you to avoid having a custom protected void makeMenu(Menu menu, int instance) method if you just want some additional screen-wise menu items. Take a look at the
public void addMenuItem(MenuItem item)
method. This way, you don't even have to extend the MainScreen - just create a basic one and and call this method for each additional menu item you want to always appear in the menu.
Saving screen contents
When you try to close a MainScreen, it checks whether there are any "dirty" (modified) fields and displays a pop-up "Changes have been made - Save, Discard, Cancel?". If you press 'Save', MainScreen's protected boolean onSave() (inherited from Screen) method is called.
You can override this pushing of the Save, Discard, Cancel dialog by overriding protected boolean onSavePrompt() method.
This behavior might catch you by surprise if you add any ButtonFields without ButtonField.NEVER_DIRTY style bit and click those before closing the screen. I know it is not exactly related to MainScreen, but it's useful to keep in mind nonetheless.
setBackground / paintBackground problem
There is a well-known and long-standing MainScreen bug: setBackground and overriding paintBackground on the MainScreen never work - the background stays white. I can only guess that their implementation is taken from Screen class, which is obviously wrong: while Screen can delegate those tasks to the delegate manager, MainScreen should go one step further and get its main manager to do that instead.
Anyway - in order to solve the problem, create a non-scrolling MainScreen (see "using style bits for customization" above) and add a (scrolling if you need it) VerticalFieldManager(USE_ALL_WIDTH | USE_ALL_HEIGHT). Add the background to this latter Manager as discussed in this knowledge base article (if you make the manager scrolling and use pre-4.6 approach, read the comment there - it's important):
Good luck customizing your MainScreen-based UI applications!