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
запас, вы могли бы просто подождать немного дольше, чтобы сделать это. Если вы подождете, пока LabelIconCommandManager
sublayout()
метод называется, ваш 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);
}
}