2

我正在开发自己的自定义管理器,到目前为止我已经完成了它,但它使用屏幕分辨率的百分比设置边距。

这是我如何调用以下类:

LabelIconCommandManager licm3 = new LabelIconCommandManager("Address blah bklahblah ", 0);
licm3.add(new ImageButtonField(b1, b2, b3, Field.FIELD_LEFT | ImageButtonField.CONSUME_CLICK));

这是类 [我在评论中标记了它返回 0 和返回 219 的位置。请告诉我为什么会发生这种情况:

public class LabelIconCommandManager extends HorizontalFieldManager implements  BCMSField
{
    LabelIconCommandManager me = this;
    EvenlySpacedHorizontalFieldManager buttonManager = new EvenlySpacedHorizontalFieldManager(0);
    LabelField labelField;
    int side = 0;
    int HPADDING = 3;
    int VPADDING = 4;
    int screenWidth = Display.getWidth();
    int labelField_width = 40;
    public LabelIconCommandManager()
    {
        this("", 0);
    }
    public LabelIconCommandManager(String label, long style)
    {
        super(USE_ALL_WIDTH| FOCUSABLE);
        this.setBorder(BorderFactory.createBitmapBorder(new XYEdges(15, 20, 15, 20),Bitmap.getBitmapResource( "border_edit.png" )));
        this.setMargin(1,10,1,10);
        labelField = new LabelField(label,LabelField.ELLIPSIS)
        {
            public void layout(int width, int height)
            {
                // Done because otherwise ellipses dont work with labelfields
                super.layout((int)(screenWidth * 0.61), getHeight());
                setExtent((int)(screenWidth * 0.61), getHeight());
                labelField_width = labelField.getWidth();
                DisplayDialog.alert("labelField_width = " + labelField_width); // returns 219
            }
        };
        // Top Right Bottom Left
        labelField.setMargin(VPADDING, HPADDING, VPADDING, 0);
        // super because we want this horizontalfieldManager to add it
        super.add(labelField);
        super.add(buttonManager);
    }
    public void alternateConstructor(Attributes atts)
    {
        labelField = new LabelField(atts.getValue("label"), 0);
    }
    public void onFocus(int direction)
    {
        this.setBorder(BorderFactory.createBitmapBorder(new XYEdges(15, 20, 15, 20),Bitmap.getBitmapResource( "border_edit_select.png" )));
        // uses the same color as listStyleButtonField selections
        this.setBackground(BackgroundFactory.createSolidBackground(0x186DEF));
        super.onFocus(direction);
    }
    //Invoked when a field loses the focus.
    public void onUnfocus()
    {
        //top, right,bottom,left
        this.setBorder(BorderFactory.createBitmapBorder(new XYEdges(15, 20, 15, 20),Bitmap.getBitmapResource( "border_edit.png" )));
        this.setBackground(BackgroundFactory.createSolidTransparentBackground(Color.GRAY, 0));
        super.onUnfocus();
        invalidate();
    }
    // Overrride this managers add function
    public void add(Field imageButton)
    {
        // Add a button to the evenly spaced manager
        buttonManager.add(imageButton);
        // Based on how many buttons there are, set the margin of where the manager holding the buttons start [offset from labelField]
        if(buttonManager.getFieldCount() == 1)
        {
            //side = (int)(screenWidth * 0.1388);
            side = screenWidth - labelField_width - 32 - 10 - 15;
            DisplayDialog.alert("Screen Width = " + screenWidth);
            DisplayDialog.alert("labelField_width2 = " + labelField_width); // returns 0
            DisplayDialog.alert("Side = " + side);
        }
        else side = (int)(screenWidth * 0.05);
        buttonManager.setMargin(0,0,0,side);
    }
    public int getLabelWidth()
    {
        return labelField_width;
    }
}  

为了更清楚,这里有一张图片:

快照

4

3 回答 3

2

注意:当我运行你的代码时,我实际上并没有看到labelField_width设置为0. 您在上面发布的代码中将值初始化为40。所以,我有时确实会看到它设置为 40 或 219(在 360 像素宽的屏幕上)。

但是,问题是我认为你试图访问的价值labelField_width太快了。唯一正确分配的位置是layout()您的匿名方法LabelField。仅仅因为您layout()根据实例化声明和实现该方法,并不意味着它在LabelField创建时被调用。这实际上是我不喜欢匿名课程的原因之一。

无论如何,这段代码:

LabelIconCommandManager licm3 = new LabelIconCommandManager("Address blah bklahblah ", 0); 
licm3.add(new ImageButtonField(b1, b2, b3, Field.FIELD_LEFT | ImageButtonField.CONSUME_CLICK));

将首先实例化LabelField(在LabelIconCommandManager构造函数内部)。正如我所说,这不会触发该layout()方法。上面的第二行 ( add()) 将触发您覆盖的方法:

// Overrride this managers add function 
public void add(Field imageButton) 
{ 

这就是您看到labelField_width. 该方法在之前被调用layout()。那就是问题所在。

由于看起来您仅使用该宽度来设置buttonManager边距,因此您可以等待更长的时间来执行此操作。如果你等到LabelIconCommandManager sublayout()方法被调用,你LabelFieldlayout()调用它的方法,并labelField_width正确分配:

protected void sublayout(int maxWidth, int maxHeight) {
   // make sure to call superclass method first!
   super.sublayout(maxWidth, maxHeight);

   // now, we can reliably use the label width:
   side = screenWidth - labelField_width - 32 - 10 - 15; 
   buttonManager.setMargin(0,0,0,side); 
}

该方法进入LabelIconCommandManager课堂。然后,您可以删除您调用的其他地方buttonManager.setMargin()

于 2012-08-01T01:17:44.713 回答
2

Nate 帖子的一些简短摘要。

当您构建管理器并添加字段时,不要期望它会正确布局。经理不知道上下文 - 它将被放置在哪里。所以只有当你将他的经理添加到屏幕上时才会调用字段的布局方法(当经理的布局也会被调用时)。这是正确的。

side变量的计算移至layout方法。

如果您side在将经理放在屏幕上之前确实需要价值。您可以通过使用Field.getPrefferedWidth()which 返回标准字段的有意义值来预先计算它(getFont().getAdvance(text)对于LabelField,也可能带有边框,请自行检查)。但要小心这个值。

于 2012-08-01T06:23:53.320 回答
1

请查看下面的代码。它是具有标签和按钮的经理。它把标签放在左边,按钮放在右边。

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.decor.Border;

import java.util.Vector;

public class TabFieldManager extends Manager {

public TabFieldManager(long style) {
    super(style);
}

protected void sublayout(int width, int height) {
    LabelField label = null;

    Vector tabs = new Vector();
    int tabsWidth = 0;
    int tabHeight = 0;
    int tabPaddingTop = 0;
    int tabPaddingLeft = 0;

    for (int i=0; i < getFieldCount(); i++) {
        Field field = getField(i);
        if (field instanceof LabelField) {
            label = (LabelField) field;
        } else if (field instanceof ButtonField){
            tabs.addElement(field);

            layoutChild(field, width, height);

            int fieldwidth = field.getWidth() > 0 ? field.getWidth() : field.getPreferredWidth() ;
            tabsWidth += fieldwidth + getBorderAndPaddingWidth(field);

            int fieldHeight = field.getHeight() > 0 ? field.getHeight() : field.getPreferredHeight();
            if (fieldHeight > tabHeight) {
                tabHeight = getBorderAndPaddingHeight(field) + fieldHeight;
            }

            int fieldPaddingTop = field.getPaddingTop();
            if (fieldPaddingTop > tabPaddingTop) {
                tabPaddingTop = fieldPaddingTop;
            }

            int fieldPaddingLeft = field.getPaddingLeft();
            if (fieldPaddingLeft > tabPaddingLeft) {
                tabPaddingLeft = fieldPaddingLeft;
            }
        }
    }

    if (label != null) {
        layoutChild(label, width - tabsWidth, height);
        int y = tabHeight - label.getHeight() >> 1;
        setPositionChild(label, tabPaddingLeft , y);
    }
    for (int i = 0; i < tabs.size(); i++) {
        Field tabField = (Field) tabs.elementAt(i);
        setPositionChild(tabField, width - tabsWidth, getBorderAndPaddingHeight(tabField));
        tabsWidth -= tabField.getWidth() + getBorderAndPaddingWidth(tabField);
    }

    setExtent(width, tabHeight);
}

private int getBorderAndPaddingHeight( Field field ) {
    int height = field.getPaddingTop() + field.getPaddingBottom();
    Border border = field.getBorder();
    if( border != null ) {
        height += border.getTop() + border.getBottom();
    }

    return height;
}

private int getBorderAndPaddingWidth( Field field ){
    int width = field.getPaddingLeft() + field.getPaddingRight();
    Border border = field.getBorder();
    if( border != null ) {
        width += border.getLeft() + border.getRight();
    }
    return width;
}

protected int moveFocus(int amount, int status, int time) {
    if ((status & Field.STATUS_MOVE_FOCUS_VERTICALLY) == Field.STATUS_MOVE_FOCUS_VERTICALLY && amount > 0) {
        return amount;
    } else
        return super.moveFocus(amount, status, time);
}

protected int nextFocus(int amount, int axis) {
    if (amount > 0 && axis == Field.AXIS_VERTICAL)
        return -1;
    else
        return super.nextFocus(amount, axis);
}

}

于 2012-08-01T14:37:42.760 回答