我找不到以下问题的解决方案。我有自定义列表字段,它与布局管理器的边界重叠。列表字段使用来自管理器的导航事件以用特殊颜色突出显示当前选定的行。布局管理器配置为支持滚动。当我向下滚动拨轮时,布局管理器调用滚动,然后将导航事件传递给它的子项,即列表字段。它会导致不正确的滚动,因为管理器将整个列表向下滚动到其底部隐藏列表行的顶部,包括选定的行。
我想要的是在当前选定的列表行仍然可见时忽略滚动,否则使用它。
我正在使用 JDE 4.2.1
我找不到以下问题的解决方案。我有自定义列表字段,它与布局管理器的边界重叠。列表字段使用来自管理器的导航事件以用特殊颜色突出显示当前选定的行。布局管理器配置为支持滚动。当我向下滚动拨轮时,布局管理器调用滚动,然后将导航事件传递给它的子项,即列表字段。它会导致不正确的滚动,因为管理器将整个列表向下滚动到其底部隐藏列表行的顶部,包括选定的行。
我想要的是在当前选定的列表行仍然可见时忽略滚动,否则使用它。
我正在使用 JDE 4.2.1
假设我们有 ListField 实现:
class LabelListField extends ListField implements ListFieldCallback {
private Vector mValues;
public LabelListField(Vector values) {
super(0);
setRowHeight(getFont().getHeight() + 10);
setCallback(this);
mValues = values;
setSize(mValues.size());
}
public void drawListRow(ListField listField, Graphics g, int index, int y,
int width) {
g.drawText((String) mValues.elementAt(index), 0, y);
}
public Object get(ListField list, int index) {
return mValues.elementAt(index);
}
public int indexOfList(ListField list, String prefix, int start) {
for (int x = start; x < mValues.size(); ++x) {
String value = (String) mValues.elementAt(x);
if (value.startsWith(prefix)) {
return x;
}
}
return -1;
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
}
如果我们想以这种方式在上下字段中对齐此列表:
ListField with scroll http://img6.imageshack.us/img6/7025/8800j.png
我们可以使用自定义管理器限制它的高度:
class ListManager extends HorizontalFieldManager {
ListField mListField;
public ListManager(ListField listField) {
super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
mListField = listField;
add(mListField);
}
public int getPreferredHeight() {
int result = Display.getHeight();
Manager manager = getManager();
if (null != manager) {
for (int i = 0, count = manager.getFieldCount(); i < count; i++) {
if (manager.getField(i) != this)
result -= manager.getField(i).getPreferredHeight();
}
}
// size down to fit max rows without splitting
result = result - result % mListField.getRowHeight();
return result;
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(maxWidth, maxHeight);
setExtent(maxWidth, getPreferredHeight());
}
}
现在我们可以使用它了:
class Scr extends FullScreen implements FieldChangeListener {
LabelField mHeader;
ListManager mHFMList;
HorizontalFieldManager mHFMButton;
LabelListField mListField;
ButtonField mButton;
public Scr() {
super(DEFAULT_MENU | DEFAULT_CLOSE);
mHeader = new LabelField("List Field", FIELD_HCENTER);
add(mHeader);
Vector values = new Vector();
values.addElement("first");
values.addElement("second");
values.addElement("third");
values.addElement("fourth");
values.addElement("fifth");
values.addElement("sixth");
values.addElement("seventh");
values.addElement("eight");
mListField = new LabelListField(values);
mHFMList = new ListManager(mListField);
add(mHFMList);
mHFMButton = new HorizontalFieldManager(FIELD_HCENTER);
add(mHFMButton);
mButton = new ButtonField("Exit", ButtonField.CONSUME_CLICK);
mButton.setChangeListener(this);
mHFMButton.add(mButton);
}
public void fieldChanged(Field field, int context) {
if (mButton == field)
close();
}
}
在 eJDE 4.2.1.17 8800 上测试
所有这些都是帮助我的解决方案。通过以这种特定方式覆盖 moveFocus,我设法修改了布局管理器中滚动的默认行为——它跳过了列表字段的第一项,允许它们保持在顶部。
public int moveFocus(int amount, int status, int time) {
invalidate(getSelectedIndex());
int unused = super.moveFocus(amount, status, time);
return Math.abs(unused) + 1;
}