Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
lostInTransit
Posts: 55
Registered: ‎03-26-2009
My Device: Not Specified
Accepted Solution

Custom ListField row with images and text

Hi

 

I am using the complex records example provided at this URL as the base for my app. What I want to do is get some data from a website's feed and display it in a ListField. Each row in the field has an image and some associated text.

 

I have made the following changes in my application implementation of the example

 

1. Creating a normal ListField instead of a subclass of ListField

 

2. Getting data from the feed and populating a Vector with the necessary information

 

3. Implementing the ListFieldCallback.

 

In the drawListRow method of the callback, I am creating an object of TableRowManager and passing the data for that particular row. Using this data, I am creating fields and adding them to the TableRowManager. Then from the drawRow method of the TableRowManager, I am calling sublayout() and specifying the x, y, width and height for each field in the TableRowManager.

 

Now when debugging the app, I see that the drawListRow method is called everytime I move around the list or when the ListField is first added to its parent. But none of the rows or fields are displayed.

 

Even drawRow is called every time from drawListRow. But the rows are never displayed. I just get a blank screen. Tried removing all the fields and keeping just one LabelField but even that is not displayed.

 

Here's the relevant code if that helps

 

TableRowManager class

private class TableRowManager extends Manager { int _index; TableRowManager(String myTxt, String msg, String imageUrl, int index) { super(0); BitmapField imgField = new WebBitmapField(imageUrl); add(imgField); LabelField personLabel = new LabelField(myTxt, DrawStyle.ELLIPSIS); add (personLabel); LabelField itemLabel = new LabelField(msg, DrawStyle.ELLIPSIS); add(itemLabel); _index = index; } public void drawRow(Graphics g, int x, int y, int width, int height) { layout(width, height); setPosition(x, y); g.pushRegion(getExtent()); g.popContext(); } protected void sublayout(int width, int height) { Field currField1 = getField(0); layoutChild(currField1, getPreferredWidth(), getPreferredHeight()); setPositionChild(currField1,0,0); Field currField2 = getField(1); layoutChild(currField2, (int) Field.USE_ALL_WIDTH, getPreferredHeight()); setPositionChild(currField2,40,80); Field currField3 = getField(2); layoutChild(currField3, (int) Field.USE_ALL_WIDTH, getPreferredHeight()); setPositionChild(currField3,40,120); setExtent(getPreferredWidth(), getPreferredHeight()); } public int getPreferredWidth() { return Display.getWidth(); } public int getPreferredHeight() { return 150; //return height of row } }

 

 

drawListRow method of the callback

public void drawListRow(ListField list, Graphics g, int index, int y, int w) { String text = (String)listElements.elementAt(index); String str1 = text.substring(0,text.indexOf("-")); String str2 = text.substring(text.indexOf("-")+2); String imageName = image[index]; String url = "http://myURL/"+imageName; TableRowManager rowManager = new TableRowManager(str1,str2,url, index); rowManager.drawRow(g, 0, y, w, list.getRowHeight()); }

 

Can someone please help me out with this. The format of what I'm trying is something like this

 

------------

| image |  LabelField1

|           |  LabelField2

-------------

 

Thanks.

Developer
Developer
rab
Posts: 283
Registered: ‎07-22-2008
My Device: Not Specified

Re: Custom ListField row with images and text

What I usually do with the listField is to draw myself the bitmap and the text, something like the following :

 

public void drawListRow(ListField list, Graphics g, int index, int y, int w)
    {
        String text = (String)listElements.elementAt(index);
        String str1 = text.substring(0,text.indexOf("-"));
        String str2 = text.substring(text.indexOf("-")+2);
        String imageName = image[index];

   

       Bitmap bitm = /* get the bitmap */ ( better to have prepared them before getting here, for performance )

     

        int xpos = LEFT_OFFSET;
        int ypos = TOP_OFFSET + y;
        int w = bitm.getWidth();
        int h = bitm.getHeight();
        int fontHeight = this.getFont().getHeight();

 

       g.drawBitmap( xpos, ypos, w, h, bitm, 0, 0 );

 

      xpos = w + SOME_OFFSET

      graphics.drawText(str1, xpos, ypos);
      ypos += fontHeight;

      graphics.drawText(str2, xpos, ypos);

      

    }

 

This worked for me all the times.

 Of course I am not suggesting that you do it this way, but I am just giving another alternative that works.

Rab

Developer
lostInTransit
Posts: 55
Registered: ‎03-26-2009
My Device: Not Specified

Re: Custom ListField row with images and text

Thanks Rab I want to use custom fields here as the bitmap is being downloaded from a server and the text needs to be displayed with a ... if it does not fit into the alloted space.

 

Any other suggestions? Thanks.

Developer
lostInTransit
Posts: 55
Registered: ‎03-26-2009
My Device: Not Specified

Re: Custom ListField row with images and text

Rab,

 

I tried the method you suggested. But it does not give me the desired layout. I get all the text in the same line. Anything beyond that is hidden.

Developer
lostInTransit
Posts: 55
Registered: ‎03-26-2009
My Device: Not Specified

Re: Custom ListField row with images and text

Just made one change to Rab's solution.

Added a line in the drawListRow method to set the row height to what I want

 

list.setRowHeight(ypos);

 

Thanks Rab. 

Developer
Developer
rab
Posts: 283
Registered: ‎07-22-2008
My Device: Not Specified

Re: Custom ListField row with images and text

Yes, I missed mentioning the setRowHeights. ( copy and paste !!)

In my original solution, I do the setRowHeight() for all rows  when I add the elements ( i.e. outside the draw method).

The reason is that I have different heights for different rows. When I did it inside the draw, you would notice a kind of flickerring in the display. The list draws at the default height, then adjust its height once the setRowHeight() is called. The effect was not acceptable.

Just in case you run into it.

 

Rab

Developer
lostInTransit
Posts: 55
Registered: ‎03-26-2009
My Device: Not Specified

Re: Custom ListField row with images and text

I did come across this issue and was wondering how to solve it. So you are using the setRowHeight(index, height) method? And where are you invoking this method?

 

Calling it in draw, I noticed that it has an effect on all the rows except the first one, which strikes to me as strange! Do you have a working solution for this problem (different row heights that is)?

 

Thanks again 

Developer
satish4ru
Posts: 329
Registered: ‎12-17-2010
My Device: Not Specified

Re: Custom ListField row with images and text

in the above program i am getting error that LEFT_OFFSET ,TOP_OFFSET  comliper  gining message that these r not initialized..

New Contributor
pedrobrigatto
Posts: 4
Registered: ‎04-05-2011
My Device: Curve 8520

Re: Custom ListField row with images and text

I am having the same problem as you. All rows are affected by this logic except the first one.

 

I tried the call to the setRowHeight() both in the end and in the beginning of the code, but no changes. And, if I am not missing anything, I do not believe this would cause any side effect to final result.

 

Does anyone has the solution to fix the problem with the first row of the list view? I am still trying, and if I find the solution I share with you all, guys. Thanks in advance for the help!

 

regards,

Pedro

New Contributor
pedrobrigatto
Posts: 4
Registered: ‎04-05-2011
My Device: Curve 8520

Re: Custom ListField row with images and text

Hi, everyone.

 

Well, I think now I solved my problem with the first row of the list. And, believe, it is quite simple.
I will put here the steps I followed, and you can try the same to see if it still works on your env.

 

1. First one, I created my custom ListField class, a CustomListField that extending ListField, and an inner class implementing the ListFieldCallback interface. This is the code:

 

 

public class CustomListField extends ListField {

  private static final String SECOND_LINE_TEXT = "Testing 2-row list field.";
  
  private Vector content = null;
  private ListCallback callback = null;
  private Font font = null;
	
  private int currentPosition = 0;
	
  /**
    * Instantiates a new title list and populates it with the appropriate items.
    *
    * @param content The content to be loaded in the list.
    */
  public CustomListField (Vector content) {
    this.content = content;
    initCallbackListening();
    font = this.getFont().derive(Font.PLAIN, 13);
    this.setFont(font);
    this.setRowHeight(-3);    // I think this is an important point for it to work: set the height of the row outside the draw method.
                              // Other possibly useful info is that the negative signal means I will multiply the font size by the number provided.
  }

  private void initCallbackListening() {
    callback = new ListCallback();
    this.setCallback(callback);
  }
	
  /**
    * Callback implementation to this custom list field. 
    * 
    * @author Pedro E. Cunha Brigatto
    */
  private class ListCallback implements ListFieldCallback {
  
    private Bitmap image = null;
    
    public ListCallback() {
      image = Bitmap.getBitmapResource("any_picture.png");
    }

    /* (non-Javadoc)
     * @see net.rim.device.api.ui.component.ListFieldCallback#drawListRow
     *  (net.rim.device.api.ui.component.ListField, net.rim.device.api.ui.Graphics, int, int, int)
     */
    public void drawListRow(ListField listField, Graphics graphics, int index, int y, int width) {
      
      int fontHeight = CustomListField.this.getFont().getHeight();
      currentPosition = index;
      int yPos = 5 + y; // initial position will consider an offset.				
      int xPos = 15; // left offset, fixed for all rows in the list.
	
      graphics.drawBitmap(5, yPos + 5, image.getWidth(), image.getHeight(), image, 0, 0);
      xPos = xPos + image.getWidth();
      graphics.setColor(Color.WHITE);   // this is because the MainScreen's background is black in my case.
      graphics.drawRect(0, y, width, 3*fontHeight);

      String text = (String)content.elementAt(index);
      graphics.setColor(Color.WHITE);
      graphics.drawText(text, xPos, yPos);
      yPos = yPos + fontHeight;				
      graphics.drawText(SECOND_LINE_TEXT, xPos, yPos);
    }

    public Object get(ListField listField, int index) {
      return content.elementAt(index);
    }

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

    public int indexOfList(ListField listField, String prefix, int start) {
      return content.indexOf(prefix, start);
    }
  }

  // This method returns the index of the highlighted item in the list, which will be useful somewhere in my code.
  public int getCurrentPosition() {
    return currentPosition;
  }	
}

 

 

Then, I just use this custom list field in the main screen implementation, as I would use the regular ListField. Like this:

 

 

public class MyMainScreen extends MainScreen {

  private Vector data = null;  // index equal to the model's title list.
  private CustomListField listField = null;   // the custom list field we've just created

  private int currentPosition = 0;

  public MyMainScreen (Vector data) {
    this.data = data;
    initComponents();
  }

  // some code here ...
  
  private void initComponents() {
 
    // building the screen ...
    this.getMainManager().setBackground(BackgroundFactory.createSolidTransparentBackground(Color.BLACK, 255));
	
    // ... some code here above
    listField = new CustomListField(data); // creating the custom list field.
    // ... more code below.
	
    add(listField);
    listField.setSize(data.size());
  } 
}

 

 

 

This is really very close to the solution Rab has provided here, and I thank him so much for it. I believe these few adaptations are really enough. To me, this code works pretty fine. But you can share here if you find any trouble on using it.

 

Best regards,

Pedro