黑莓如何设计屏幕就像网格视图

时间:2014-06-09 07:03:23

标签: eclipse image user-interface blackberry

我是黑莓开发的新手,我甚至不知道如何开始。我已经从它的官方网站上阅读了部分内容

http://developer.blackberry.com/devzone/files/design/bb7/UI_Guidelines_BlackBerry_Smartphones_7_1.pdf

和其他如此多的链接,但我不能发布所有的链接,因为它说,如果你想发布更多的链接,那么你必须有10个声誉,我没有那么抱歉,

现在我的问题是我想设计像http://postimg.org/image/we3leycsd/

这样的布局

我如何设计这种布局呢?我正在使用eclipse进行黑莓开发。

请帮助我已经尝试了很多东西,但我无法做到这一点。

您的任何帮助将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我会在里面创建一个包含n HorizontalFieldManager的自定义VerticalFieldManager,然后覆盖adddelete方法。这是我之前做过的,应该适合你,它将新字段添加到最短的列。

StaggeredListView.java:

public class StaggeredListView extends HorizontalFieldManager
{
    private int column_spacing = 0;

    public StaggeredListView(int columns)
    {
        super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR | NO_HORIZONTAL_SCROLL | NO_HORIZONTAL_SCROLLBAR | USE_ALL_WIDTH);

        if (columns < 1)
        {
            throw new RuntimeException("Number of columns needs to be larger than 0.");
        }

        final int width = Display.getWidth() / columns;

        for (int i = 0; i < columns; i++)
        {
            VerticalFieldManager vfm = new VerticalFieldManager(NO_VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR | NO_HORIZONTAL_SCROLL | NO_HORIZONTAL_SCROLLBAR)
            {
                protected void sublayout(int maxWidth, int maxHeight)
                {
                    maxWidth = Math.min(width, getPreferredWidth());
                    maxHeight = Math.min(maxHeight, getPreferredHeight());
                    super.sublayout(width, maxHeight);
                    super.setExtent(width, maxHeight);
                }
            };
            super.add(vfm);
        }
    }

    public int getColumnCount()
    {
        return getFieldCount();
    }

    /**
     * Sets the spacing between columns.
     * 
     * <p>
     * Spacing between fields is <i><b>not</b></i> set.
     * </p>
     */
    public void setColumnSpacing(int spacing)
    {
        if (spacing < 0) throw new RuntimeException("Column spacing my not be negative.");

        int length = getColumnCount();
        for (int i = 1; i < length; i++)
        {
            ((VerticalFieldManager) getField(i)).setPadding(0, 0, 0, spacing);
        }

        column_spacing = spacing;
    }

    /**
     * Get the value currently assigned via the {@link #setColumnSpacing(int)} method.
     * 
     * @return
     */
    public int getColumnSpacing()
    {
        return column_spacing;
    }

    /**
     * Deletes all fields from each of the columns.
     */
    public void clear()
    {
        int length = getColumnCount();
        for (int i = 0; i < length; i++)
        {
            ((VerticalFieldManager) getField(i)).deleteAll();
        }
    }

    /**
     * Delete specified field from the columns.
     * 
     * <p>
     * Does <b><i>not</i></b> rearrange fields.
     * </p>
     */
    public void delete(Field field)
    {
        int length = getColumnCount();
        for (int i = 0; i < length; i++)
        {
            try
            {
                ((VerticalFieldManager) getField(i)).delete(field);
                break;
            } catch (IllegalArgumentException e)
            {
                // field not in this manager
            }
        }
    }

    /**
     * Adds the field to the column with the least height.
     */
    public void add(Field field)
    {
        // find the vfm with least height
        int index = 0;
        int height = ((VerticalFieldManager) getField(index)).getPreferredHeight();

        int length = getColumnCount();
        for (int i = 1; i < length; i++)
        {
            int temp_height = ((VerticalFieldManager) getField(i)).getPreferredHeight();
            if (temp_height < height)
            {
                height = temp_height;
                index = i;
            }
        }

        ((VerticalFieldManager) getField(index)).add(field);
    }
}

至于包含在其中的项目,我会创建一个带有图像和文本的字段,然后自己绘制它(我有很多焦点问题,并且发现使用绘画更容易)。 您可以使用它来制作BaseButton http://developer.blackberry.com/bbos/java/documentation/tutorial_create_custom_button_1969896_11.html

BaseButton.java:

public abstract class BaseButton extends Field
{
    // flags to indicate the current visual state
    protected boolean _visible = true;
    protected boolean _active;
    protected boolean _focus;

    protected boolean drawfocus = false;

    private int touch_top = 0;
    private int touch_right = 0;
    private int touch_bottom = 0;
    private int touch_left = 0;

    protected boolean fire_on_click = true; // false fires on unclick

    public BaseButton()
    {
        this(0);
    }

    public BaseButton(long style)
    {
        super((style & Field.NON_FOCUSABLE) == Field.NON_FOCUSABLE ? style : style | Field.FOCUSABLE);
    }

    /**
     * Sets the radius around the button to trigger touch events.
     * <p>
     * (0,0,0,0) by default.
     * </p>
     */
    public void setTouchRadius(int top, int right, int bottom, int left)
    {
        touch_top = top;
        touch_right = right;
        touch_bottom = bottom;
        touch_left = left;
    }

    protected void onFocus(int direction)
    {
        _focus = true;
        invalidate();
        super.onFocus(direction);
    }

    protected void onUnfocus()
    {
        if (_active || _focus)
        {
            _focus = false;
            _active = false;
            invalidate();
        }
        super.onUnfocus();
    }

    public void set_visible(boolean visible)
    {
        _visible = visible;
        invalidate();
    }

    public boolean is_visible()
    {
        return _visible;
    }

    protected void drawFocus(Graphics g, boolean on)
    {
        if (drawfocus) super.drawFocus(g, on);
    }

    protected void layout(int width, int height)
    {
        setExtent(Math.min(width, getPreferredWidth()), Math.min(height, getPreferredHeight()));
    }

    protected boolean keyUp(int keycode, int time)
    {
        if (Keypad.map(Keypad.key(keycode), Keypad.status(keycode)) == Characters.ENTER)
        {
            _active = false;
            invalidate();
            return true;
        }

        return false;
    }

    protected boolean keyDown(int keycode, int time)
    {
        if (Keypad.map(Keypad.key(keycode), Keypad.status(keycode)) == Characters.ENTER)
        {
            _active = true;
            invalidate();
        }

        return super.keyDown(keycode, time);
    }

    protected boolean keyChar(char character, int status, int time)
    {
        if (character == Characters.ENTER)
        {
            clickButton();
            return true;
        }

        return super.keyChar(character, status, time);
    }

    protected boolean navigationClick(int status, int time)
    {
        if (status != 0)
        { // non-touch event
            _active = true;
            invalidate();
            if (fire_on_click) clickButton();
        }
        return true;
    }

    protected boolean trackwheelClick(int status, int time)
    {
        if (status != 0)
        { // non-touch event
            _active = true;
            invalidate();
            if (fire_on_click) clickButton();
        }
        return true;
    }

    protected boolean navigationUnclick(int status, int time)
    {
        if (status != 0)
        { // non-touch event
            _active = false;
            invalidate();
            if (!fire_on_click) clickButton();
        }
        return true;
    }

    protected boolean trackwheelUnclick(int status, int time)
    {
        if (status != 0)
        { // non-touch event
            _active = false;
            invalidate();
            if (!fire_on_click) clickButton();
        }
        return true;
    }

    protected boolean invokeAction(int action)
    {
        switch (action)
        {
            case ACTION_INVOKE :
            {
                clickButton();
                return true;
            }
        }

        return super.invokeAction(action);
    }

    protected boolean touchEvent(TouchEvent message)
    {
        boolean isOutOfBounds = touchEventOutOfBounds(message);
        switch (message.getEvent())
        {
            case TouchEvent.CLICK :
                if (!_active)
                {
                    _active = true;
                    invalidate();
                }

                if (!isOutOfBounds)
                {
                    if (fire_on_click) clickButton();
                    return true;
                }

            case TouchEvent.DOWN :
                if (!isOutOfBounds)
                {
                    if (!_active)
                    {
                        _active = true;
                        invalidate();
                    }
                    return true;
                }
                return false;

            case TouchEvent.UNCLICK :
                if (_active)
                {
                    _active = false;
                    invalidate();
                }

                if (!isOutOfBounds)
                {
                    if (!fire_on_click) clickButton();
                    return true;
                }

            case TouchEvent.UP :
                if (_active)
                {
                    _active = false;
                    invalidate();
                }

            default :
                return false;
        }
    }

    private boolean touchEventOutOfBounds(TouchEvent message)
    {
        int x = message.getX(1);
        int y = message.getY(1);
        return (x < 0 - touch_left || y < 0 - touch_top || x > getWidth() + touch_right || y > getHeight() + touch_bottom);
    }

    public void setDirty(boolean dirty)
    {
    }

    public void setMuddy(boolean muddy)
    {
    }

    public void clickButton()
    {
        if (_visible) fieldChangeNotify(0);
    }
}

ImageSubtitleButton.java:

public class ImageSubtitleButton extends BaseButton
{
    private static final int FOCUS_THINKNESS = 2;
    String title;
    Bitmap image_default;

    int height;

    public ImageSubtitleButton(String title, String image_default)
    {
        this.image_default = Bitmap.getBitmapResource(image_default);
        setTitle(title);
    }

    public void setTitle(String title)
    {
        this.title =  title;
        height = image_default.getHeight() + getFont().getHeight()  + (FOCUS_THINKNESS * 2);

        updateLayout();
        invalidate();
    }

    public int getPreferredWidth()
    {
        return Math.max(getFont().getAdvance(title), image_default.getWidth());
    }

    public int getPreferredHeight()
    {
        return height;
    }

    protected void paint(Graphics graphics)
    {
        int x = (getWidth() - image_default.getWidth()) / 2;
        int y = 0;
        graphics.drawBitmap(x, y, image_default.getWidth(), image_default.getHeight(), image_default, 0, 0);

        if (_focus)
        {
            graphics.setColor(Color.BLUE); // your focus colour
            for (int i = 0; i < FOCUS_THINKNESS; i++)
            {
                graphics.drawRect(x + i, y + i, image_default.getWidth() - (i * 2), image_default.getHeight() - (i * 2));
            }
        }

        graphics.setColor(Color.BLACK);
        y = image_default.getHeight();
            graphics.drawText(title, x, y);
    }
}

现在您可以按如下方式将这些内容添加到屏幕中:

StaggedListView listview = new StaggedListView(2);
ImageSubtitleButton button = new ImageSubtitleButton("test", "test.png");
listview.add(button);
add(listview);

您需要设置ImageSubtitleButton的首选宽度和高度,以使其保持一致,就像您发布的示例图片一样。

答案 1 :(得分:1)

道歉,我没有时间创建完整的答案,但我个人不会使用HFM / VFM组合来做到这一点。而是使用一个提供网格的管理器。如果您使用的是足够晚的操作系统,则可以使用GridFieldManager执行此操作,

GridFieldManager

但我与该经理有过不同的经历。所以我通常使用这个经理:

TableLayoutManager

我希望这能帮到你。