Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
457 views
in Technique[技术] by (71.8m points)

java - Custom List Field click event

i m writing one application in which i have created custom list field for displaying listview. my CustomListField contains one image and text in a row. i m gettiing field change listener on click of listfield row but i want to put fieldchange listener on image too.. can anyone tell me how can i do that.

here is my code.

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

i want to put click listner on star image of listfield row

and following is output of abbove code. enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I did something very similar to this on a past project:

Background

As Arhimed said in his answer, and as you can read about on the BlackBerry forums here, you can't have full-fledged Field objects within the ListField. The content of ListField rows is just drawn directly in drawListRow() as text, and Bitmaps, etc. The contents aren't Field instances, and therefore, are not focusable.

So, what I did was to replace ListField with a subclass of Manager. Originally, I used a VerticalFieldManager, but I ran into problems with that. I've also been seeing a lot of issues on stack overflow, where people subclass VerticalFieldManager, customize just one small behaviour, and everything starts breaking. It seems to me that VerticalFieldManager works well if you accept its normal behaviour, and if you need something more, just extend Manager directly. Performing layout for vertically stacked rows is pretty easy.

I then made each row its own Manager, and implemented custom layout in sublayout() to place the row's Fields where I wanted them. I could then also make the row focusable, and then a bitmap/button on the row separately focusable (like your star). Clicking the row invokes one action, and clicking the star invokes another one.

I will note, however, that in my app, performance was not an issue, because I only had 10-20 rows. Also, I did have to modify my code to match your example, so consider this code only lightly tested. However, I did build it into an app, so it should perform fine as long as my assumptions, and your description were valid.

Implementation

First, it wasn't clear to me what your ListRander is (you didn't show that code). However, in my code, I need a data class to contain details about one row. It looked like that's how you used ListRander, so that's what I used:

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

Then, I replaced your CustomListField class with my own:

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

Finally, one row is represented by my CustomListRow class:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...