tags:

views:

905

answers:

1

I'm trying to create a Help/About screen for my application, but I've discovered that, well, my code sucks. (I know it could use a little refactoring, but when working with a new framework I get the code working first then immediately go back and refactor to do things "properly").

First, what I'm doing doesn't "feel" like the right way of doing it. I'm not sure about just stuffing a bunch of text fields into the layout - is there a better way of doing so?

Second, the VFM is taking up the bulk of the screen and pushing my 'Close' button off the bottom. What I'm trying to do is keep the title and 'Close' button visible but just scroll the VFM.

How can I solve these problems?

public class HelpScreen extends PopupScreen {
    public HelpScreen() {
     super(new VerticalFieldManager(), Field.FOCUSABLE);

     /* Construct the Close button */
     FieldChangeListener listener = new FieldChangeListener() {
      public void fieldChanged(Field field, int context) {
       ok();
      }
     };
     ButtonField b = new ButtonField("Close", Field.FIELD_HCENTER);
     b.setChangeListener(listener);

     /* Construct the text box containing the help */
     VerticalFieldManager vfm = new VerticalFieldManager(VERTICAL_SCROLL);
     TextField f;
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("My application does stuff. This part is the description of what it does.");
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("Commands:");
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("N - New Widget");
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("R - Rename Widget");
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("D - Duplicate Widget");
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("C - Clear Widget");
     vfm.add(f = new TextField(FIELD_LEFT | READONLY));
     f.setText("Shift-Delete - Delete Widget");

     /* Construct the screen */
     add(new LabelField("About Widget Wiffleball", Field.FIELD_HCENTER));
     add(new SeparatorField());
     add(vfm);
     add(b);
    }

    public void ok() {
     UiApplication.getUiApplication().popScreen(this);
    }
}
+2  A: 

For the code not 'feeling right' - functionally it seems fine, but a bit of refactoring could clean it up a bit - maybe make a method to create and populate the TextFields

private TextField createTextField(String content) {
    TextField textField = new TextField(
}

Then that portion of the constructor becomes:

VerticalFieldManager vfm = new VerticalFieldManager(VERTICAL_SCROLL);
vfm.add(createTextField("My application does stuff. This part is the description of what it does."));
vfm.add(createTextField("Commands:"));
vfm.add(createTextField("N - New Widget"));
vfm.add(createTextField("R - Rename Widget"));
vfm.add(createTextField("D - Duplicate Widget"));
vfm.add(createTextField("C - Clear Widget"));
vfm.add(createTextField("Shift-Delete - Delete Widget"));

You solve the layout problem using a custom field manager - really not difficult, you just have to subclass Manager and implement sublayout. Define a 'top', 'bottom', and 'middle' field, and layout accordingly (some code left out as an exercise to the reader, but basically when adding fields to the manager you'll need to be able to specify one as top and one as bottom. The following logic will make sure the bottom field is always stuck to the bottom, and the top 2 fields don't push it off the bottom:

protected void sublayout(int width, int height) {
    // retrieve the top, middle and bottom fields

    int heightRemaining = height; 

    layoutChild(topField, width, heightRemaining);
    setPositionChild(topField, 0, 0);

    heightRemaining -= topField.getHeight();

    layoutChild(bottomField, width, heightRemaining);
    setPositionChild(bottomField, 0, height - bottomField.getHeight());

    heightRemaining -= bottomField.getHeight();

    layoutChild(middleField, width, heightRemaining);
    setPositionChild(middleField, 0, topField.getHeight());

}

Again, just a framework - no error checking or anything in there. Then set your delegate to be this new manager, set your vertical field manager to be the middle field (you'll probably want a designated setter), your button field to the bottom field (again, designated getter).

Anthony Rizk
Thanks - I'll try that out. I know some refactoring would help; when working with a new framework I tend to just "get it working" then go back and immediately refactor. The "not feeling right" comes from the fact that it seems a little hackish to use a bunch of text fields. On the other hand, perhaps that *is* the right way.
MikeyB