labelField.getWidth() возвращает 0? Почему это происходит?

Я работаю над собственным настраиваемым менеджером, и до сих пор я его выполнил, но он устанавливает маржи, используя процент разрешения экрана.

Вот как я называю следующий класс:

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

Вот картинка, чтобы быть более ясной:

снимок

3 ответа

Решение

Примечание: когда я запускал твой код, я фактически не видел 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 запас, вы могли бы просто подождать немного дольше, чтобы сделать это. Если вы подождете, пока LabelIconCommandManagersublayout() метод называется, ваш LabelField будет иметь свое layout() метод называется, и 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(),

Краткое резюме из поста Нейта.

Когда вы создаете менеджер и добавляете поля, не ожидайте, что он будет правильно размещен. Менеджер не знает контекст - где он будет размещен. Поэтому метод макета для поля будет вызываться только при добавлении его менеджера на экран (когда также будет вызываться макет для менеджера). И это правильно.

Переместить расчет вашего side переменная к layout метод.

Если вам действительно нужно side значение, прежде чем положить менеджер на экран. Вы можете рассчитать его с помощью Field.getPrefferedWidth() который возвращает значимые значения для стандартных полей (getFont().getAdvance(text) за LabelField, вероятно, также с границами, пожалуйста, проверьте себя). Но будьте осторожны с этими ценностями.

Пожалуйста, просмотрите код ниже. Это менеджер, который имеет ярлык и кнопки. И это помещает этикетку слева и кнопки справа.

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

}

Другие вопросы по тегам