Ответ 1
Итак, в полях BlackBerry размер - это фактический визуальный размер поля. Но виртуальная степень - это логический размер, который он может использовать, некоторые из которых могут быть не видны. Для Managers
, который вы хотите иметь прокрутку, вы обычно устанавливаете виртуальную степень больше, чем размер.
Я использовал эту концепцию для динамического изменения виртуальной протяженности вашего HorizontalFieldManager
, основываясь на том, сколько пространства в настоящее время необходимо, чтобы едва соответствовать тексту в BasicEditField
. Чтобы сделать это, я должен был позволить HorizontalFieldManager
прослушать изменения в BasicEditField
, выполнив FieldChangeListener
. Затем, когда каждый символ вводится в поле редактирования, диспетчер горизонтальных полей пересчитывает, сколько ширины требуется для количества текста, который теперь находится в поле. Затем он снова устанавливает виртуальную ширину в эту ширину.
Это приводит к тому, что диспетчер горизонтального поля разрешает прокрутку только до конца введенного текста, а не справа, так как исходный код был выполнен.
Итак, я не думаю, что BlackBerry делал что-то неправильно... никаких ошибок в ОС. Раньше виртуальная степень просто не была установлена.
Я разделил свой HorizontalFieldManager на новый частный класс, потому что мне не нравится использовать анонимные классы, когда логика превышает примерно 5 строк кода. Итак, нижеприведенное решение выглядит несколько иначе.
Другие мысли:
1) В результате попытки рисования границы с пользовательской реализацией paint()
появляются рисунки артефактов. Но эта ошибка была изначально там, и я решил этот вопрос о проблеме прокрутки. Похоже, вы пытались использовать объекты Border
, что, вероятно, является лучшим способом достижения границы для поля прокрутки.
2) С моим новым решением фактический класс CustomTextField
в нем мало. Это только контейнер (Manager
) для CustomHorizontalFieldManager
. Возможно, вы могли бы избавиться от этого внешнего слоя, если хотите. Но я знаю, что иногда, когда вы отправляете код, вы удаляете детали, которые не важны для того, с чем вы столкнулись. Таким образом, возможно наличие VerticalFieldManager
содержит a HorizontalFieldManager
, который содержит a BasicEditField
. Я оставлю это для вас... это будет только необязательная очистка.
3) Я тестировал это на симуляторе 5.0 Storm2.
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.util.Arrays;
public class CustomTextField extends VerticalFieldManager {
private int textWidth = 0;
private int textHeight = 0;
private CustomHorizontalFieldManager hfm;
public CustomTextField(int width, int height) {
super();
textWidth = width;
textHeight = height;
hfm = new CustomHorizontalFieldManager();
add(hfm);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(textWidth, textHeight);
setExtent(textWidth, textHeight);
}
protected void paint(Graphics graphics) {
// TODO: change me!
super.paint(graphics);
graphics.setColor(Color.BLACK);
graphics.drawRect(0, 0, textWidth, textHeight);
}
private class CustomHorizontalFieldManager extends HorizontalFieldManager implements FieldChangeListener {
private BasicEditField basicEditField;
/** the maximum virtual width of the edit field, based on the max num of chars */
private int maxVirtualWidth;
public CustomHorizontalFieldManager() {
super(Manager.HORIZONTAL_SCROLL);
int maxNumChars = 200;
basicEditField = new BasicEditField("", "", maxNumChars, BasicEditField.NO_NEWLINE);
// determine how wide the field would need to be to hold 'maxNumChars', with the font
// in use ... just pick a long string of all W's, since that usually the widest char
char[] buffer = new char[maxNumChars];
Arrays.fill(buffer, 'W');
String spacer = new String(buffer);
maxVirtualWidth = basicEditField.getFont().getAdvance(spacer);
// we need to listen as the user types in this field, so we can dynamically alter its
// virtual width
basicEditField.setChangeListener(this);
add(basicEditField);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(maxWidth, maxHeight);
// extent is the visible size, virtual extent can be wider if we want scrolling
setExtent(textWidth, textHeight);
setVirtualExtent(maxVirtualWidth, textHeight);
}
public void fieldChanged(Field f, int context) {
if (f == basicEditField) {
// recalculate how much virtual width the edit field needs, based on the
// current text content
int newWidth = basicEditField.getFont().getAdvance(basicEditField.getText());
setVirtualExtent(newWidth, textHeight);
}
}
}
}