Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Eclipse Blackberry如何设计类似屏幕的网格视图_Eclipse_Image_User Interface_Blackberry - Fatal编程技术网

Eclipse Blackberry如何设计类似屏幕的网格视图

Eclipse Blackberry如何设计类似屏幕的网格视图,eclipse,image,user-interface,blackberry,Eclipse,Image,User Interface,Blackberry,我对黑莓的开发非常陌生,甚至不知道如何开始。我已经从它的官方网站上读到了部分内容 和其他这么多的链接,但我不能发布所有的链接,因为它说,如果你想发布更多的链接,那么你必须有10个声誉,我没有,所以很抱歉 现在我的问题是我想设计这样的布局 我怎样才能设计出这样的布局呢。我正在使用eclipse进行Blackberry开发 请帮助我,我已经尝试了很多事情,但我无法做到这一点 您的任何帮助都将不胜感激。提前谢谢。我将创建一个自定义的水平字段管理器,其中包含n垂直字段管理器,然后覆盖添加和删除方法。这

我对黑莓的开发非常陌生,甚至不知道如何开始。我已经从它的官方网站上读到了部分内容


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

现在我的问题是我想设计这样的布局

我怎样才能设计出这样的布局呢。我正在使用eclipse进行Blackberry开发

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


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

我将创建一个自定义的
水平字段管理器
,其中包含n
垂直字段管理器
,然后覆盖
添加
删除
方法。这是我以前做的,应该对你有用,它将新字段添加到最短的列中

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

您需要设置
ImageSubtitle按钮的首选宽度和高度,使其保持一致,如您发布的示例图像所示。

我将创建一个自定义
HorizontalFieldManager
,其中包含n
VerticalFieldManager
,然后覆盖
add
delete
方法。这是我以前做的,应该对你有用,它将新字段添加到最短的列中

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

您需要设置
ImageSubtitle按钮的首选宽度和高度,使其保持一致,如您发布的示例图像所示。

我将创建一个自定义
HorizontalFieldManager
,其中包含n
VerticalFieldManager
,然后覆盖
add
delete
方法。这是我以前做的,应该对你有用,它将新字段添加到最短的列中

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

您需要设置
ImageSubtitle按钮的首选宽度和高度,使其保持一致,如您发布的示例图像所示。

我将创建一个自定义
HorizontalFieldManager
,其中包含n
VerticalFieldManager
,然后覆盖
add
delete
方法。这是我以前做的,应该对你有用,它将新字段添加到最短的列中

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

您需要设置
ImageSubtitle按钮的首选宽度和高度,以保持一致,如您发布的示例图像所示。

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

但我和那位经理的经历不一。所以我通常使用这个管理器:


我希望这能让你顺利进行。

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

但我和那位经理的经历不一。所以我通常使用这个管理器:


我希望这能让你顺利进行。

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

但我和那位经理的经历不一。所以我通常使用这个管理器:


我希望这能让你顺利进行。

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

但我和那位经理的经历不一。所以我通常使用这个管理器:



我希望这能让您继续学习。

如何将此代码添加到我的类中?对不起,我是黑莓的新手,我什么都不知道。不要!把它封装起来。而是为
交错列表视图
创建一个新类,为
基本按钮
创建一个新类,为扩展
基本按钮的
图像按钮
创建一个新类。因此,稍后您可以像添加任何其他字段一样添加它们。感谢您的快速回复,但我不知道必须在
ImageButton
类和
BaseButton
类中添加什么。然后我如何在我的UI类中调用这些。我知道这是一个有点长的过程,我问,但我真的不明白。如果你能帮我的话,那就太棒了。我提供的链接几乎完全是
BaseButton
中的链接,如果你先试试,那就太好了,但我会马上把这两个类添加到我的答案中。好的,谢谢你的回复,我会尽力解决它,但如果可能的话,发布代码。谢谢你的帮助。我怎样才能把这些代码添加到我的课堂上?对不起,我是黑莓的新手,我什么都不知道。不要!把它封装起来。而是为
交错列表视图
创建一个新类,为
基本按钮
创建一个新类,为扩展
基本按钮的
图像按钮
创建一个新类。因此,稍后您可以像添加任何其他字段一样添加它们。感谢您的快速回复,但我不知道必须在
ImageButton
类和
BaseButton
类中添加什么。然后我如何在我的UI类中调用这些。我知道这是一个有点长的过程,我问,但我真的不明白。如果你能帮我,那真是太好了