gpt4 book ai didi

java - 自定义列表字段点击事件

转载 作者:搜寻专家 更新时间:2023-11-01 01:13:48 25 4
gpt4 key购买 nike

我正在编写一个应用程序,在其中创建了用于显示listview的自定义列表字段。
我的CustomListField连续包含一个图像和文本。我在单击列表字段行时获取字段更改侦听器,但我也想在图像上放置字段更改侦听器。
谁能告诉我该怎么做。

这是我的代码。

public class CustomListField extends ListField implements ListFieldCallback {
private Vector _listData;
private int _MAX_ROW_HEIGHT = 60;

public CustomListField(Vector data) {
_listData = data;
setSize(_listData.size());
setSearchable(true);
setCallback(this);
setRowHeight(_MAX_ROW_HEIGHT);
}

protected void drawFocus(Graphics graphics, boolean on) {
XYRect rect = new XYRect();
graphics.setGlobalAlpha(150);
graphics.setColor(Color.BLUE);
getFocusRect(rect);
drawHighlightRegion(graphics, HIGHLIGHT_FOCUS, true, rect.x, rect.y, rect.width, rect.height);
}

public int moveFocus(int amount, int status, int time) {
this.invalidate(this.getSelectedIndex());
return super.moveFocus(amount, status, time);

}

public void onFocus(int direction) {
super.onFocus(direction);
}

protected void onUnFocus() {
this.invalidate(this.getSelectedIndex());
}

public void refresh() {
this.getManager().invalidate();
}

public void drawListRow(ListField listField, Graphics graphics, int index, int y, int w) {
listField.setBackground(BackgroundFactory.createBitmapBackground(Bitmap.getBitmapResource("listing_bg.png")));
ListRander listRander = (ListRander) _listData.elementAt(index);

graphics.setGlobalAlpha(255);
graphics.setFont(Font.getDefault().getFontFamily().getFont(Font.PLAIN, 24));

final int margin = 5;
final Bitmap thumb = listRander.getListThumb();
final String listHeading = listRander.getListTitle();
final Bitmap nevBar = listRander.getNavBar();

// list border
graphics.setColor(Color.GRAY);
graphics.drawRect(0, y, w, _MAX_ROW_HEIGHT);

// thumbnail border & thumbnail image
graphics.setColor(Color.BLACK);
// graphics.drawRoundRect(margin-2, y+margin-2,thumb.getWidth()+2, thumb.getHeight()+2, 5, 5);
graphics.drawBitmap(margin, y + margin, thumb.getWidth(), thumb.getHeight(), thumb, 0, 0);

// drawing texts
// graphics.setFont(Font.BOLD);
graphics.drawText(listHeading, margin + thumb.getWidth(), y + margin);
graphics.setColor(Color.GRAY);
// graphics.setFont(Font.smallFont); // graphics.drawText(listDesc, 2*margin+thumb.getWidth(), y+ margin+20); // //
// graphics.drawText(listDesc2, 2*margin+thumb.getWidth(), y+ margin+32);

// draw navigation button
final int navBarPosY = y + (_MAX_ROW_HEIGHT / 2 - nevBar.getHeight() / 2);
final int navBarPosX = Graphics.getScreenWidth() - nevBar.getWidth() + margin;
graphics.drawBitmap(navBarPosX, navBarPosY, nevBar.getWidth(), nevBar.getHeight(), nevBar, 0, 0);
}

public Object get(ListField listField, int index) {
String rowString = (String) _listData.elementAt(index);
return rowString;
}

public int indexOfList(ListField listField, String prefix, int start) {
for (Enumeration e = _listData.elements(); e.hasMoreElements();) {
String rowString = (String) e.nextElement();
if (rowString.startsWith(prefix)) {
return _listData.indexOf(rowString);
}
}
return 0;
}

public int getPreferredWidth(ListField listField) {
return 3 * listField.getRowHeight();

}

/*
protected boolean trackwheelClick(int status, int time) {
invalidate(getSelectedIndex());
Dialog.alert(" U have selected :" + getSelectedIndex());
return super.trackwheelClick(status, time);
}
*/
}

我想将点击列表框放在列表框行的星标上

以下是上述代码的输出。

最佳答案

我在过去的项目中做了与此非常相似的事情:

背景

As Arhimed said in his answer,并且您可以阅读有关on the BlackBerry forums here的信息,因此Field中没有完整的ListField对象。 ListField行的内容只是直接在drawListRow()中绘制为文本和位图等内容。这些内容不是Field实例,因此无法聚焦。

所以,我要做的是用ListField的子类替换Manager。最初,我使用了VerticalFieldManager,但是遇到了问题。我还看到了很多关于堆栈溢出的问题,人们将子类VerticalFieldManager子类化,仅自定义一种小行为,一切就开始崩溃。在我看来,如果您接受VerticalFieldManager的正常行为,它就可以很好地工作;如果您需要更多其他功能,只需直接扩展Manager。对垂直堆叠的行执行布局非常容易。

然后,我将每一行设置为自己的Manager,并在sublayout()中实现自定义布局,以将该行的Field放置在我想要的位置。然后,我还可以使行可聚焦,然后使行上的位图/按钮可分别聚焦(例如您的星星)。单击该行将调用一个动作,而单击星号将调用另一个动作。

但是,我会注意到,在我的应用程序中,性能不是问题,因为我只有10-20行。另外,我确实必须修改我的代码以匹配您的示例,因此请仅对该代码进行轻微测试。但是,我确实将其构建到应用程序中,因此只要我的假设和您的描述有效,它就可以正常运行。

实作

首先,我不清楚您的ListRander是什么(您未显示该代码)。但是,在我的代码中,我需要一个数据类来包含有关一行的详细信息。看起来这就是您使用ListRander的方式,所以这就是我所使用的方式:

public class ListRander {

private String _title;
private Bitmap _thumb;

public ListRander(String title, Bitmap thumb) {
_title = title;
_thumb = thumb;
}

public String getTitle() {
return _title;
}
public Bitmap getThumb() {
return _thumb;
}
}

然后,我用自己的CustomListField类替换了:

public class CustomListField extends Manager implements FocusChangeListener {

private int _MAX_ROW_HEIGHT = 60;
private boolean _searchable = false;
private Vector _listData;
private FieldChangeListener _fieldListener;

public CustomListField(Vector data) {
super(FOCUSABLE | VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
setSearchable(true);
setEditable(false);
setListData(data);
}

public void setChangeListener(FieldChangeListener listener) {
// we need to save this listener, because we set it to listen to all new rows
_fieldListener = listener;
int numFields = getFieldCount();
for (int f = 0; f < numFields; f++) {
getField(f).setChangeListener(listener);
}
super.setChangeListener(listener);
}

public int getRowHeight() {
return _MAX_ROW_HEIGHT;
}

public void setSearchable(boolean searchable) {
_searchable = searchable;
}

public int getSelectedIndex() {
return getFieldWithFocusIndex(); // TODO??
}

public Object get(int index) {
return _listData.elementAt(index);
}

public int indexOfList(String prefix, int start) {
if (start >= _listData.size() || !_searchable) {
return -1;
} else {
int result = getSelectedIndex(); // the default result if we find no matches
for (Enumeration e = _listData.elements(); e.hasMoreElements(); ) {
String rowString = (String) e.nextElement();
if (rowString.startsWith(prefix)) {
return _listData.indexOf(rowString);
}
}
return result;
}
}

protected boolean navigationClick(int status, int time) {
CustomListRow focus = (CustomListRow) getFieldWithFocus();
if (focus != null) {
// see if the row wants to process this click
if (!focus.navigationClick(status, time)) {
// let our FieldChangeListener know that this row has been clicked
fieldChangeNotify(getFieldWithFocusIndex());
}
return true;
} else {
return false;
}
}

protected void sublayout(int width, int height) {
int w = Math.min(width, getPreferredWidth());
int h = Math.min(height, getPreferredHeight());
int rowHeight = getRowHeight();
int numRows = getFieldCount();

setExtent(w, h);
setVirtualExtent(w, rowHeight * numRows);

for (int i = 0; i < numRows; i++) {
Field f = getField(i);
setPositionChild(f, 0, rowHeight * i);
layoutChild(f, w, rowHeight);
}
}

public int getPreferredWidth() {
return Display.getWidth();
}

public int getPreferredHeight() {
return Display.getHeight();
}

public void setListData(Vector listData) {
_listData = listData;
if (listData != null) {
int listSize = listData.size();
int numRows = getFieldCount();
for (int s = 0; s < listSize; s++) {
if (s < numRows) {
// we can reuse existing CustomListRows
CustomListRow row = (CustomListRow) getField(s);
row.setData((ListRander) listData.elementAt(s));
} else {
CustomListRow row = new CustomListRow((ListRander) listData.elementAt(s));
row.setChangeListener(_fieldListener);
row.setFocusListener(this);
add(row);
}
}

if (listSize < numRows) {
// delete the excess rows
deleteRange(listSize, numRows - listSize);
}
} else {
deleteAll();
}
invalidate();
}

public void focusChanged(Field field, int eventType) {
// we handle scrolling here, when focus changes between rows
if (eventType == FOCUS_GAINED) {
if (field.getTop() < getVerticalScroll()) {
// field is off the top of the screen, so scroll up
setVerticalScroll(field.getTop());
} else if (field.getTop() >= getVerticalScroll() + getVisibleHeight()) {
// field is off the bottom of the screen, so scroll down
setVerticalScroll(field.getTop() - getVisibleHeight() + getRowHeight());
}
}
}
}

最后,一行由我的CustomListRow类表示:

public class CustomListRow extends Manager implements FieldChangeListener {

private static final int _MAX_ROW_HEIGHT = 60;
private ListRander _data;
private BitmapField _thumb;
private LabelField _title;
private FocusableBitmapField _star;
private static final Bitmap _starImg = Bitmap.getBitmapResource("star.png");
private static final Bitmap _bgImg = Bitmap.getBitmapResource("listing_bg.png");
private SeparatorField _separator;
private int _fontColor = Color.BLACK;
private boolean _highlighted = false;
private int _width;

// subclass exists to expose focus methods (make public)
private class FocusableBitmapField extends BitmapField {
public FocusableBitmapField() {
super(_starImg, BitmapField.FOCUSABLE | BitmapField.EDITABLE);
}
public void onFocus(int direction) {
super.onFocus(direction);
}
public void onUnfocus() {
super.onUnfocus();
}
}

public CustomListRow(ListRander data) {
super(Field.FOCUSABLE | Manager.NO_VERTICAL_SCROLL | Manager.NO_VERTICAL_SCROLLBAR);

setBackground(BackgroundFactory.createBitmapBackground(_bgImg));
_width = Display.getWidth();

long labelStyle = (DrawStyle.LEFT | DrawStyle.TOP | DrawStyle.ELLIPSIS);
_title = new LabelField("", labelStyle) { // custom anonymous class to change font color
protected void paint(Graphics g) {
int c = g.getColor();
g.setColor(_fontColor);
super.paint(g);
g.setColor(c);
}
};
_title.setFont(Font.getDefault().getFontFamily().getFont(Font.PLAIN, 24));

_thumb = new BitmapField();

_star = new FocusableBitmapField();
_star.setChangeListener(this);

_separator = new SeparatorField() { // custom anonymous class to change separator color
protected void paint(Graphics g) {
int c = g.getColor();
g.setColor(Color.GRAY);
super.paint(g);
g.setColor(c);
}
};

setData(data);

add(_thumb);
add(_title);
add(_star);
add(_separator);
}

public ListRander getData() {
return _data;
}

public void setData(ListRander value) {
if (value != _data) {
_data = value;

_title.setText(value.getTitle());
_thumb.setBitmap(value.getThumb());
}
}

private void onStarClicked() {
Dialog.alert("Star has been clicked or tapped!");
}

private void onRowClicked() {
Dialog.alert("Row has been clicked or tapped!");
}

public void fieldChanged(Field field, int context) {
if (field == _star) {
onStarClicked();
}
}

public boolean navigationClick(int status, int time) {
if (_star.isFocus()) {
onStarClicked();
return true;
} /* else {
onRowClicked();
return true;
} */
return false; // we will not consume this event
}

protected void highlight(boolean onRow) {
_fontColor = onRow ? Color.WHITE : Color.BLACK; // change font color for contrast
_highlighted = onRow;
invalidate();
}

protected void onFocus(int direction) {
// called when focus first transfers to this row, from another Field
if (direction == 1) {
// coming from top to bottom, we highlight the row first, not the star
highlight(true);
} else if (direction == -1) {
// coming from bottom to top, we highlight the star button first, not the row
_star.onFocus(direction);
highlight(false);
}
}

protected void onUnfocus() {
// remove highlighting of the row, if any
highlight(false);
super.onUnfocus();
}

protected int moveFocus(int amount, int status, int time) {
// called when this row already has focus (either on row, or star button)
if (amount > 0) {
// moving top to bottom
if (!_star.isFocus()) {
// we were on the row, now move to the star button
_star.onFocus(1);
highlight(false);
amount--; // consume one unit of movement
}
} else {
// moving from bottom to top
if (_star.isFocus()) {
// we were on the star button, now move back over to the row
_star.onUnfocus();
highlight(true);
amount++; // consume one unit of movement
}
}
return amount;
}

protected boolean touchEvent(net.rim.device.api.ui.TouchEvent event) {
// We take action when the user completes a click (a.k.a. unclick)
int eventCode = event.getEvent();
if ((eventCode == TouchEvent.UNCLICK) || (eventCode == TouchEvent.DOWN)) {
// Get the touch location, within this Manager
int x = event.getX(1);
int y = event.getY(1);

if ((x >= 0) && (y >= 0) && (x < _width) && (y < _MAX_ROW_HEIGHT)) {
int field = getFieldAtLocation(x, y);
if ((field >= 0) && (getField(field) == _star)) {
// Let event propagate to (star) button field
return super.touchEvent(event);
} else {
if (eventCode == TouchEvent.UNCLICK) {
// A completed click anywhere else in this row should popup details for this selection
fieldChangeNotify(1);
onRowClicked();
} else {
// This is just a soft touch (TouchEvent.DOWN), without full click
setFocus();
}
// Consume the event
return true;
}
}
}
// Event wasn't for us, let superclass handle in default manner
return super.touchEvent(event);
}

protected void sublayout(int width, int height) {
height = Math.min(getPreferredHeight(), height);
setExtent(_width, height);

final int margin = 5;

int thumbWidth = _thumb.getPreferredWidth();
layoutChild(_thumb, thumbWidth, _thumb.getPreferredHeight());
setPositionChild(_thumb, margin, margin);

int starWidth = _star.getPreferredWidth();
int starHeight = _star.getPreferredHeight();
layoutChild(_star, starWidth, starHeight);
setPositionChild(_star, width - starWidth - margin, (height - starHeight) / 2);

// this assumes you want margin between all fields, and edges
layoutChild(_title, width - thumbWidth - starWidth - 4 * margin, _title.getPreferredHeight());
setPositionChild(_title, margin + thumbWidth /* + margin */, margin); // TODO?
}

protected void paintBackground(Graphics g) {
super.paintBackground(g);
if (_highlighted) {
// you can't override drawFocus() for a Manager, so we'll handle that here:
int oldColor = g.getColor();
int oldAlpha = g.getGlobalAlpha();
XYRect rect = new XYRect();
g.setGlobalAlpha(150);
g.setColor(Color.BLUE);
getFocusRect(rect);
drawHighlightRegion(g, HIGHLIGHT_FOCUS, true, rect.x, rect.y, rect.width, rect.height);
g.setGlobalAlpha(oldAlpha);
g.setColor(oldColor);
}
}

public int getPreferredWidth() {
return _width;
}

public int getPreferredHeight() {
return _MAX_ROW_HEIGHT;
}
}

用法

这是您可能会使用整个列表字段的方法(可能在Screen类中):

public class ListScreen extends MainScreen implements FieldChangeListener {
public ListScreen() {
try {
Vector data = new Vector();
Bitmap icon = Bitmap.getBitmapResource("list_icon.png");
for (int i = 0; i < 15; i++) {
ListRander lr = new ListRander("Product Name " + i, icon);
data.addElement(lr);
}
CustomListField list = new CustomListField(data);
add(list);
list.setChangeListener(this);
} catch (Exception e) {
e.printStackTrace();
}
}

public void fieldChanged(Field field, int context) {
if (field instanceof CustomListRow) {
CustomListRow row = (CustomListRow) field;
Dialog.alert(row.getData().getTitle() + " was selected!");
}
}
}

在我的应用程序中,CustomListRow本身可以处理相当于您的星形点击的操作。但是,对我来说,以这种方式处理点击并没有使
有意义。因此,我让您在 FieldChangeListener本身上设置一个 CustomListField,当选择任何行时会对其进行回调。请参阅上面的屏幕课程示例。如果您想处理该行,也可以在 CustomListRow类内部单击,也可以。我在那里布置了 onRowClicked()方法。在代码中搜索被注释掉的位置,然后可以重新激活该方法的实现( onRowClicked())。

问题
  • 我的应用程序不需要列表搜索。我布置了一个示例实现,就像ListField一样。但是,我没有测试。这是您的工作,如果需要的话。我只是让您开始使用CustomListField实现(请参阅indexOfList())。
  • 我看不到您的“导航栏”是干什么的。条通常是全角项目,例如状态栏或工具栏。在您的屏幕截图中我看不到任何类似的东西。导航项可能是每行右侧的小箭头,以显示详细信息。但是,我也没有在您的屏幕截图中看到这一点。因此,我忽略了该代码。如果您需要导航栏,您显然知道它应该是什么,可以将其添加到上面的代码中。
  • 我不知道您是否只是将星星添加为行的背景图像的一部分,或者是否为此添加了单独的图像。我添加了一个单独的 star.png 来代表星星。我假设单击星标可以将其填充或突出显示。但是,您没有描述该问题,因此我认为您可以解决。如果您需要一个自定义字段来代表恒星(可以选择和不选择图像),只需将其发布为新问题即可。
  • 您似乎出现了一些代码,试图将行宽设置为行高的3倍,但这与您的屏幕截图不符。无论如何,大多数列表都是全屏宽度。因此,我删除了该代码。我的CustomListRow类实现getPreferredWidth()并请求全屏宽度。如果愿意,请更改。
  • 关于java - 自定义列表字段点击事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11483128/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com