views:

338

answers:

1

I am writing an app for Blackberry and I have the following problem:

I have implemented a custom field by extending the Manager class. The field is quite simple, it consists of a label and two check boxes, yes and no. The fields are laid out so that the label is on the left and uses as much space as it can while still allowing room for the check boxes which are positioned next to each other at the right and vertically centred compared to the label (if it spans more than one line). So it looks like this:

This is a question? O Yes O No

Everything is fine so far in terms of laying out the fields. But now I am trying to handle focus traversal. First of all the default behaviour when the user scrolls up or down is to move between the yes and no options. I want to move to the next field above or below when up or down is pressed, so I did this:

protected int moveFocus(int amount, int status, int time) {
    if (status == 537001984 || status == -1610481664) { // Up or down was pressed
        // Don't move focus between yes and no when up or down is pressed.
        return amount;
    }
    return super.moveFocus(amount, status, time);
}

And that seems to work.

The next thing I would like to do is to remember which option last had the focus when the field loses focus, then on gaining focus again (regardless of which direction the focus comes from) set this field to have the focus. I tried overriding onUnfocus and onFocus so that onUnfocus I note which field was focussed then onFocus setFocus to that field. But I get a StackOverflowError, I guess because the call to setFocus on a field within the manager actually calls onFocus for the manager itself again??

So does anyone know how I should be doing this? I checked the DateField and it has the exact behaviour I am looking for, i.e. it remembers if you were last on the day, month or year field and sets this field to focus when the field itself gets the focus.

+2  A: 

When I need to correct focus inside onFocus, I am using some flag:

boolean isCustomFocusSet = false;

protected void onFocus(int direction) {
    if (!isCustomFocusSet) {            
        isCustomFocusSet = true;
        int fieldIndex = getLastFocusedCBIndex();
        CustomField field = (CustomField)getField(fieldIndex);
        field.setFocus();
    } else {
        isCustomFocusSet = false;
        super.onFocus(direction);           
    }
}   

UPDATE For CustomField this may resolve to call this.onFocus instead of super.onFocus:

CustomField field = (CustomField)getField(fieldIndex);
Max Gontar
Thanks for the reply. I tried it out and it sorted the problem of the StackOverflow Error, but I found that calling field.setFocus() only actually causes onFocus to be called sometimes (possibly the first time the field ever gains focus). So the first time my CustomField gains focus this works as expected, but after that onFocus alternates between calling field.setFocus and super.onFocus. Any idea why field.setFocus only causes onFocus to be called again on some occasions and not all the time?
DaveJohnston
maybe it's because of using abstract Field class? see update
Max Gontar
no, because in my case I am accessing the fields directly rather than using getField(fieldIndex), i.e. based on my flag for what field was the last focussed I call either yesField.setFocus or noField.setFocus, both of which are standard RadioButtonFields.When I referred to CustomField above I was talking about the container (Manager class).
DaveJohnston