views:

513

answers:

1

Thanks to Max in this post, I made an horizontal menu. But now I'm trying to make an overlay menu, i I don't find how to do that... Let's see what i got first.

So, I have a class MapScreen which display my map:

public class MapScreen extends MenuScreen

Then, I have in the same file the MenuScreen class like this that allows to display the horizontal menu when I press the MENU key:

abstract class MenuScreen extends MainScreen {
boolean mMenuEnabled = false;
CyclicHFManager mMenuManager = null;

public MenuScreen() {
    mMenuManager = new CyclicHFManager();
    mMenuManager.setBorder(BorderFactory.createBevelBorder(new XYEdges(4,
            0, 0, 0), new XYEdges(Color.DARKBLUE, 0, 0, 0), new XYEdges(
            Color.WHITE, 0, 0, 0)));
    mMenuManager.setBackground(BackgroundFactory
            .createLinearGradientBackground(Color.DARKBLUE, Color.DARKBLUE,
                    Color.LIGHTBLUE, Color.LIGHTBLUE));


    for (int i = 0; i < 10; i++) {
        Bitmap nBitmap = new Bitmap(60, 60);
        Graphics g = new Graphics(nBitmap);
        g.setColor(Color.DARKBLUE);
        g.fillRect(0, 0, 60, 60);
        g.setColor(Color.WHITE);
        g.drawRect(0, 0, 60, 60);
        Font f = g.getFont().derive(Font.BOLD, 40);
        g.setFont(f);
        String text = String.valueOf(i);
        g.drawText(text, (60 - f.getAdvance(text)) >> 1, (60 - f
                .getHeight()) >> 1);

        Bitmap fBitmap = new Bitmap(60, 60);
        g = new Graphics(fBitmap);
        g.setColor(Color.DARKBLUE);
        g.fillRect(0, 0, 60, 60);
        g.setColor(Color.GOLD);
        g.drawRect(0, 0, 60, 60);
        g.setFont(f);
        g.drawText(text, (60 - f.getAdvance(text)) >> 1, (60 - f
                .getHeight()) >> 1);

        BitmapButtonField button = new BitmapButtonField(nBitmap, fBitmap);
        button.setCookie(String.valueOf(i));
        button.setPadding(new XYEdges(0, 18, 0, 18));

        button.setChangeListener(new FieldChangeListener() {
            public void fieldChanged(Field field, int context) {
                Dialog.inform("Button # " + (String) field.getCookie());
            }
        });

        mMenuManager.add(button);
    }
}

protected boolean keyDown(int keycode, int time) {
    if (Keypad.KEY_MENU == Keypad.key(keycode)) {
        if (mMenuManager.getManager() != null) {
            delete(mMenuManager);
            mMenuManager.mCyclicTurnedOn = false;
        } else {
            add(mMenuManager);
            mMenuManager.getField(2).setFocus();
            mMenuManager.mCyclicTurnedOn = true;
        }
        return true;
    } else {
        return super.keyDown(keycode, time);
    }
}}

And finally my menu manager:

public class CyclicHFManager extends HorizontalFieldManager {
int mFocusedFieldIndex = 0;
public boolean mCyclicTurnedOn = false;

public void focusChangeNotify(int arg0) {
    super.focusChangeNotify(arg0);
    if (mCyclicTurnedOn) {
        int focusedFieldIndexNew = getFieldWithFocusIndex();
        if (focusedFieldIndexNew != mFocusedFieldIndex) {
            if (focusedFieldIndexNew - mFocusedFieldIndex > 0)
                switchField(0, getFieldCount() - 1);
            else
                switchField(getFieldCount() - 1, 0);
        }
    } else {
        mFocusedFieldIndex = getFieldWithFocusIndex();
    }
}

private void switchField(int prevIndex, int newIndex) {
    Field field = getField(prevIndex);
    delete(field);
    insert(field, newIndex);
}}

So as it is like this, it is working: when I press the MENU key, the menu appears, i can navigate between buttons, and it disappear when I press again the same key. The only problem is my menu isn't overlaying my map, it pushes the content up. I tried with the menu manager like in your first response, resizing the content manager but it is the same result.

Max gave me the link http://stackoverflow.com/questions/1497073/blackberry-fields-layout-animation to do so, but I really don't know how to use it to make it work in my project...

Thank you for your help!

UPDATE

This works great, it's what I wanted. However, I still have a problem because I'm under 4.5. So first in the MenuHostManager constructor, I deleted the

USE_ALL_HEIGHT  

and change

setPositionChild(mMenuManager, 0, 
    Display.getHeight() - mMenuManager.getPreferredHeight());  

like this to have the menu at the bottom of the screen. It worked.

Then, instead of drawing my bitmaps, I did this:

Bitmap nBitmap = EncodedImage.getEncodedImageResource("menu" + 
    i + ".png").getBitmap();
BitmapButtonField button = new BitmapButtonField(nBitmap, nBitmap);

And it worked too (no rollover for now, later). So it is great!
I also overwrite the Paint method of my CyclicHFManager to have a background color, because I can't use the BorderFactory and BackgroundFactory... My menu bar has a color for now so it's ok.
Then, because of these 2 classes missing, in my BitmapButtonField I had to delete the 2 setBorder functions that change the borders. And now i have my buttons pretty big like normal buttons with borders...
How can I make the same effect as the setBorder functions under 4.5? (BTW, setBorder is not working under 4.5 too...).
Thank you!

UPDATE 2

See the screen with 5.0 with this code:

public BitmapButtonField(Bitmap normal, Bitmap focused) {
    super(CONSUME_CLICK);
    mNormal = normal;
    mFocused = focused;
    mWidth = mNormal.getWidth();
    mHeight = mNormal.getHeight();
    setMargin(0, 0, 0, 0);
    setPadding(0, 0, 0, 0);
    setBorder(BorderFactory
            .createSimpleBorder(new XYEdges(0, 0, 0, 0)));
    setBorder(VISUAL_STATE_ACTIVE, BorderFactory
            .createSimpleBorder(new XYEdges(0, 0, 0, 0)));
}

Screenshot: i45.tinypic.com/4sz85u.jpg

And under 4.5 with the 2 setBorder functions deleted (because not available):

public BitmapButtonField(Bitmap normal, Bitmap focused) {
    super(CONSUME_CLICK);
    mNormal = normal;
    mFocused = focused;
    mWidth = mNormal.getWidth();
    mHeight = mNormal.getHeight();
    setMargin(0, 0, 0, 0);
    setPadding(0, 0, 0, 0);
}

Screenshot: i49.tinypic.com/rartz5.jpg

And I would like the first screenshot under 5.0 but with 4.5!

UPDATE 3

I solved the problem by adding

protected void applyTheme() {

}

There are no more borders and it looks great!

I need to focus on my rollover now, then the click action (I have no dialog box when I click on it on the simulator). I also succeed changing the background of my menu manager, I draw a picture because I can't use BackgroundFactory.createLinearGradientBackground.

How can I manage my rollover when you do have the getVisualState() function?

UPDATE 4

I change the BitmapButtonField a bit to make it rollover without using getVisualState(). I don't know if it's really good to do that, but it is working (I used a temp bitmap mCurrent):

public class BitmapButtonField extends ButtonField {
Bitmap mNormal;
Bitmap mFocused;
Bitmap mCurrent;

int mWidth;
int mHeight;

public BitmapButtonField(Bitmap normal, Bitmap focused) {
    super(CONSUME_CLICK);
    mNormal = normal;
    mFocused = focused;
    mCurrent = normal;
    mWidth = mNormal.getWidth();
    mHeight = mNormal.getHeight();
    setMargin(0, 0, 0, 0);
    setPadding(0, 0, 0, 0);
}

protected void onFocus(int direction) {
    mCurrent = mFocused;  
    invalidate();
}

protected void onUnfocus() {
    mCurrent = mNormal;
    invalidate();
}

protected void paint(Graphics graphics) {
    Bitmap bitmap = mCurrent;   
    graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
            bitmap, 0, 0);
}

protected void applyTheme() {

}

public int getPreferredWidth() {
    return mWidth;
}

public int getPreferredHeight() {
    return mHeight;
}

protected void layout(int width, int height) {
    setExtent(mWidth, mHeight);
}
}

UPDATE 5

I found the solution. My menu is now working! Thank you for your help about everything on this topic! I might open a new topic for the menu itself, because not sure to do a cyclic one (complicated because of different screen size and resolution to be centered and have the icon all the time in the middle.) See below the code in my MapScreen.java

protected boolean navigationMovement(int dx, int dy, int status, int time) {
    if (mMenuHostManager.isActive()) {
        return super.navigationMovement(dx, dy, status, time);
    }
    return mapField.navigationMovement(dx, dy, status, time);
}

protected boolean navigationClick(int status, int time) {
    if (mMenuHostManager.isActive()) {
        return super.navigationClick(status, time);
    }
    return true;
}

protected boolean navigationUnclick(int status, int time) {
    if (mMenuHostManager.isActive()) {
        return super.navigationUnclick(status, time);
    }
    return true;
}
A: 

alt text alt text

Hi! Screen has its own content manager and unfortunately we cannot make custom sublayout on screen level. You will have to move menu into separate manager.

See full code:

class Scr extends MenuScreen {
    public Scr() {
        mMenuHostManager.add(new LabelField(
                "Lorem ipsum dolor sit amet, consectetur "
                        + "adipiscing elit. Vestibulum egestas eleifend "
                        + "urna, in dictum erat auctor ac. Integer "
                        + "volutpat ultricies mauris eu accumsan. "
                        + "Quisque at euismod dui. Phasellus "
                        + "faucibus orci id libero interdum a "
                        + "feugiat lacus sodales. Nullam "
                        + "pulvinar vestibulum dolor "
                        + "rhoncus tristique."));
    }
}

class MenuScreen extends MainScreen {
    MenuHostManager mMenuHostManager;

    public MenuScreen() {
        mMenuHostManager = new MenuHostManager();
        add(mMenuHostManager);
    }

    protected boolean keyDown(int keycode, int time) {
        if (Keypad.KEY_MENU == Keypad.key(keycode)) {
            mMenuHostManager.toggleMenu();
            return true;
        } else {
            return super.keyDown(keycode, time);
        }
    }
}

class MenuHostManager extends HorizontalFieldManager {
    CyclicHFManager mMenuManager = null;

    public MenuHostManager() {
        super(USE_ALL_WIDTH | USE_ALL_HEIGHT);
        mMenuManager = new CyclicHFManager();
        mMenuManager.setBorder(BorderFactory.createBevelBorder(
                new XYEdges(4, 0, 0, 0), new XYEdges(Color.DARKBLUE, 0, 0,
                        0), new XYEdges(Color.WHITE, 0, 0, 0)));
        mMenuManager.setBackground(BackgroundFactory
                .createSolidTransparentBackground(Color.DARKBLUE, 100));

        for (int i = 0; i < 10; i++) {
            Bitmap nBitmap = new Bitmap(60, 60);
            Graphics g = new Graphics(nBitmap);
            g.setColor(Color.DARKBLUE);
            g.fillRect(0, 0, 60, 60);
            g.setColor(Color.WHITE);
            g.drawRect(0, 0, 60, 60);
            Font f = g.getFont().derive(Font.BOLD, 40);
            g.setFont(f);
            String text = String.valueOf(i);
            g.drawText(text, (60 - f.getAdvance(text)) >> 1, (60 - f
                    .getHeight()) >> 1);

            Bitmap fBitmap = new Bitmap(60, 60);
            g = new Graphics(fBitmap);
            g.setColor(Color.DARKBLUE);
            g.fillRect(0, 0, 60, 60);
            g.setColor(Color.GOLD);
            g.drawRect(0, 0, 60, 60);
            g.setFont(f);
            g.drawText(text, (60 - f.getAdvance(text)) >> 1, (60 - f
                    .getHeight()) >> 1);

            BitmapButtonField button = new BitmapButtonField(nBitmap,
                    fBitmap);
            button.setCookie(String.valueOf(i));
            button.setPadding(new XYEdges(0, 18, 0, 18));

            button.setChangeListener(new FieldChangeListener() {
                public void fieldChanged(Field field, int context) {
                    Dialog
                            .inform("Button # "
                                    + (String) field.getCookie());
                }
            });

            mMenuManager.add(button);
        }
    }

    protected void sublayout(int width, int height) {
        super.sublayout(width, height);
        if (mMenuManager.getManager() != null) {
            layoutChild(mMenuManager, mMenuManager.getPreferredWidth(),
                    mMenuManager.getPreferredHeight());
            setPositionChild(mMenuManager, 0, 0);
        }

    }

    public void toggleMenu() {
        if (mMenuManager.getManager() != null) {
            delete(mMenuManager);
            mMenuManager.mCyclicTurnedOn = false;
        } else {
            add(mMenuManager);
            updateLayout();
            mMenuManager.getField(2).setFocus();
            mMenuManager.mCyclicTurnedOn = true;
        }
    }
}

class CyclicHFManager extends HorizontalFieldManager {
    int mFocusedFieldIndex = 0;
    public boolean mCyclicTurnedOn = false;

    public void focusChangeNotify(int arg0) {
        super.focusChangeNotify(arg0);
        if (mCyclicTurnedOn) {
            int focusedFieldIndexNew = getFieldWithFocusIndex();
            if (focusedFieldIndexNew != mFocusedFieldIndex) {
                if (focusedFieldIndexNew - mFocusedFieldIndex > 0)
                    switchField(0, getFieldCount() - 1);
                else
                    switchField(getFieldCount() - 1, 0);
            }
        } else {
            mFocusedFieldIndex = getFieldWithFocusIndex();
        }
    }

    private void switchField(int prevIndex, int newIndex) {
        Field field = getField(prevIndex);
        delete(field);
        insert(field, newIndex);
    }
}

class BitmapButtonField extends ButtonField {
    Bitmap mNormal;
    Bitmap mFocused;
    Bitmap mActive;

    int mWidth;
    int mHeight;

    public BitmapButtonField(Bitmap normal, Bitmap focused) {
        super(CONSUME_CLICK);
        mNormal = normal;
        mFocused = focused;
        mWidth = mNormal.getWidth();
        mHeight = mNormal.getHeight();
        setMargin(0, 0, 0, 0);
        setPadding(0, 0, 0, 0);
        setBorder(BorderFactory
                .createSimpleBorder(new XYEdges(0, 0, 0, 0)));
        setBorder(VISUAL_STATE_ACTIVE, BorderFactory
                .createSimpleBorder(new XYEdges(0, 0, 0, 0)));
    }

    protected void paint(Graphics graphics) {
        Bitmap bitmap = null;
        switch (getVisualState()) {
        case VISUAL_STATE_NORMAL:
            bitmap = mNormal;
            break;
        case VISUAL_STATE_FOCUS:
            bitmap = mFocused;
            break;
        case VISUAL_STATE_ACTIVE:
            bitmap = mFocused;
            break;
        default:
            bitmap = mNormal;
        }
        graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
                bitmap, 0, 0);
    }

    public int getPreferredWidth() {
        return mWidth;
    }

    public int getPreferredHeight() {
        return mHeight;
    }

    protected void layout(int width, int height) {
        setExtent(mWidth, mHeight);
    }
}
Max Gontar
Max, again, thank you! This works great, it's what I wanted. However, I still have a problem because I'm under 4.5.So first in the MenuHostManager constructor, I deleted the USE_ALL_HEIGHT and change setPositionChild(mMenuManager, 0, Display.getHeight() - mMenuManager.getPreferredHeight()); like this to have the menu at the bottom of the screen. It worked. Then, instead of drawing my bitmaps, I did this: Bitmap nBitmap = EncodedImage.getEncodedImageResource("menu" + i + ".png").getBitmap();BitmapButtonField button = new BitmapButtonField(nBitmap, nBitmap);
Dachmt
And it worked too (no rollover for now, later). So it is great! I also overwrite the Paint method of my CyclicHFManager to have a background color, because I can't use the BorderFactory and BackgroundFactory... My menu bar has a color for now so it's ok. Then, because of these 2 classes missing, in my BitmapButtonField I had to delete the 2 setBorder functions that change the borders. And now i have my buttons pretty big like normal buttons with borders... How can I make the same effect as the setBorder functions under 4.5? (BTW, setBorder is not working under 4.5 too...). Thank you!
Dachmt
You're welcome! :) For large text better to update question or even create new one. However that would be duplicate in this case: for border in 4.5 take look at http://stackoverflow.com/questions/1135349/blackberry-how-to-add-border-to-basiceditfield
Max Gontar
I solved the border problem, see update 3! I need to find out how to do the rollover because i can't use getVisualState() in my Paint function...
Dachmt
I solved this one too, see update 4. Please tell me if it's correct! Now, I have a focus problem... on the Simulator 8330 for example it's working, but on the device (bold 9000) or a Simulator 9630 it focus on my map, not the menu.
Dachmt
In my MapScreen class (extends MenuScreen), I have the navigationMovement() that I use for navigation in my map. I had to check if the focus was on the menu, if yes I return false otherwise i do my changes on the map (it means the user is not on the menu and navigating the map). I noticed that the left and right trackball isn't working, i have to use up and down to navigate between my buttons! Any idea how to solve this that I can do both? going left for the previous button and right for the next...
Dachmt
update 4 is ok, you could use custom state also: http://code.google.com/p/bbpuzzled/source/browse/trunk/BBPuzzled/src/org/ci/blackberry/ui/BitmapButtonField45.java?r=3 Sorry, I can't help with focus issue on different devices. When you say navigationMovement left and right not working, you mean dx = 0?
Max Gontar
It depends, but dx = 0, 1 or -1 depending what I do with the trackball. So it receives the navigation correctly when I'm focus on the menu or on the map (when I disable the menu and I'm back on the map, I can go in every direction). It's just it doesn't want to change fields, and it draws a white background behind. I read things with the onFocus fucntion, I'm gonna try this today but if you have any suggestions, I take it!Thank you!
Dachmt
See update 5 for the focus and click problem!
Dachmt
Thank you Max again :)
Dachmt
You're welcome Dachmt! Sorry I can't help with additional questions!
Max Gontar
Do you have any tips to centered the buttons? I mean depending on screens' sizes and resolutions, having an odd number of buttons to center focus on the middle one? I saw one of your reponse but it uses libraries superior than 4.5, so I can't use it (the Advanced UI thing).Thanks!
Dachmt
Max Gontar
Oh yeah, sorry about that. I didn't see that was 4.2 and over... I just have problems with the preprocessing when I add the API files from the source they give.
Dachmt
Do you know why the focus goes to far when I scroll fast? Because my menu is centered and everything works fine, except if i scroll too fast it goes to the next field and it's pretty annoying... That's my last problem! Should I see that in the navigationMovement() too?Thanks!
Dachmt
I can only guess, but maybe system continue processing focus change event without waiting for CyclicHFManager.focusChangeNotify to complete field switch. Try to play with thread.sleep to slowdown scrolling in menu bar field or handle case when focus is not on the center field (and move it back explicitly)
Max Gontar