黑莓自定义覆盖水平菜单

3

感谢这篇文章中的Max,我制作了一个水平菜单。但现在我想要做一个覆盖菜单,但我不知道如何做...先看看我得到了什么。

所以,我有一个名为MapScreen的类,它显示我的地图:

public class MapScreen extends MenuScreen

然后,我在同一个文件中有MenuScreen类,当我按下MENU键时可以显示水平菜单:

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);
    }
}}

最后是我的菜单管理器:

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);
}}

所以现在的情况是这样的:当我按下MENU键时,菜单出现了,我可以在按钮之间导航,当我再次按下相同的键时,它会消失。唯一的问题是我的菜单没有覆盖我的地图,而是将内容向上推。我尝试使用菜单管理器,就像您第一次回复中所说的那样,调整内容管理器的大小,但结果仍然是一样的。
Max给了我这个链接Blackberry - fields layout animation,但我真的不知道如何在我的项目中使用它来使其工作...
谢谢你的帮助!
更新
这很好用,正是我想要的。然而,我仍然有一个问题,因为我使用的是4.5版本。因此,在MenuHostManager构造函数中,我删除了


USE_ALL_HEIGHT  

并且改变

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

我这样做可以让菜单位于屏幕底部,它有效了。

接着,我不再绘制我的位图,而是这样做:

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

它也起作用了(暂时没有翻转,稍后)。所以这很棒!
我还重写了我的CyclicHFManager的Paint方法,以拥有一个背景颜色,因为我不能使用BorderFactory和BackgroundFactory...我的菜单栏现在有一个颜色,所以没问题了。
然后,由于这两个类缺失,在我的BitmapButtonField中,我不得不删除改变边框的两个setBorder函数。现在我的按钮很大,就像普通按钮一样有边框...
如何在4.5下实现与setBorder函数相同的效果?(顺便说一句,setBorder在4.5下也不起作用...)。
谢谢!

更新2

请查看使用此代码的5.0屏幕。

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)));
}

截图:i45.tinypic.com/4sz85u.jpg

如果删除了两个setBorder函数(因为不可用),则版本应低于4.5:

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);
}

截图:i49.tinypic.com/rartz5.jpg

我希望第一张截图在4.5版本下显示,而不是5.0版本下。

更新3

我通过添加代码解决了这个问题。

protected void applyTheme() {

}

没有更多的边界,看起来很棒!

我现在需要专注于我的滑过效果,然后是点击动作(当我在模拟器上单击时,没有对话框)。我还成功地更改了我的菜单管理器的背景,因为我无法使用BackgroundFactory.createLinearGradientBackground,所以我画了一张图片。

当你有getVisualState()函数时,我该如何管理我的滑过效果?

更新4

我稍微改变了BitmapButtonField,使其可以在不使用getVisualState()的情况下滑过。我不知道这样做是否真的好,但它确实有效(我使用了一个临时位图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);
}
}

更新 5

我找到了解决方案。我的菜单现在可以正常工作了!感谢您在这个话题上的所有帮助!我可能会为菜单本身开启一个新话题,因为不确定是否要做循环的(由于不同屏幕尺寸和分辨率而变得复杂,并始终将图标居中)。请参见下面的代码,位于我的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;
}

谢谢更新的 BitmapButtonField,它节省了我的时间。 - Dhruv
1个回答

0

alt text http://img534.imageshack.us/img534/9679/overlay1o.jpg alt text http://img243.imageshack.us/img243/4176/overlay2.jpg

你好!屏幕有自己的内容管理器,不幸的是我们不能在屏幕级别上制作自定义子布局。您将不得不将菜单移动到单独的管理器中。

查看完整代码:

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,再次感谢!这很好用,正是我想要的。但是,我仍然有一个问题,因为我的版本低于4.5。所以首先在MenuHostManager构造函数中,我删除了USE_ALL_HEIGHT并将setPositionChild(mMenuManager, 0, Display.getHeight() - mMenuManager.getPreferredHeight());更改为这样,使菜单位于屏幕底部。它起作用了。然后,我没有绘制我的位图,而是这样做:Bitmap nBitmap = EncodedImage.getEncodedImageResource("menu" + i + ".png").getBitmap();BitmapButtonField button = new BitmapButtonField(nBitmap, nBitmap); - Dachmt
而且它也起作用了(现在没有翻转,以后再说)。所以这很棒!我还覆盖了我的CyclicHFManager的Paint方法,以便有一个背景颜色,因为我不能使用BorderFactory和BackgroundFactory...我的菜单栏现在有一个颜色,所以没问题。然后,由于这两个类缺失,在我的BitmapButtonField中,我不得不删除那两个改变边框的setBorder函数。现在我的按钮非常大,就像普通带边框的按钮一样...如何在4.5下实现与setBorder函数相同的效果?(顺便说一句,setBorder在4.5下也不起作用...)。谢谢! - Dachmt
不客气! :) 对于大段文本最好更新问题或者创建新的问题。但是在这种情况下会有重复:对于边框为4.5,请参考https://dev59.com/H0jSa4cB1Zd3GeqPFXOE - Maksym Gontar
我解决了边框问题,请看更新3!我需要找出如何执行鼠标悬停,因为我无法在我的Paint函数中使用getVisualState()... - Dachmt
在我的MapScreen类(扩展MenuScreen),我有navigationMovement()方法,用于在地图中导航。我必须检查焦点是否在菜单上,如果是,则返回false,否则我会对地图进行更改(这意味着用户不在菜单上并且正在浏览地图)。我注意到左右轨迹球不起作用,我必须使用上下键在按钮之间导航!有什么办法可以解决这个问题,让我既可以向左移动到上一个按钮,又可以向右移动到下一个按钮... - Dachmt
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接