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
Trusted Contributor
Posts: 145
Registered: ‎01-23-2012
My Device: 9300
My Carrier: airtel
Accepted Solution

Adding static button in a Scrollable list

Hi all,

 

I am adding a list in to verticalFieldManager with vertical scroll feature, and in the same manger in bottom  I need to add a button(after clicking on button I have to go on other screen).

 

 Here my problem is that whenever I scroll the list, the button should not scroll, it should look like the button on the top of the scroll view and the list in the back ground. But whenever I scroll the list , list has to scroll in button back ground.

 

 For more clarification I am adding a screen shot please find the attachment.

  

Developer
Posts: 19,616
Registered: ‎07-14-2008
My Device: Not Specified

Re: Adding static button in a Scrollable list

[ Edited ]

What you are asking is difficult.  I can think of two ways to do this, one of which will only work on a touch screen.  So let us try the other option first.

 

You will need to create a Manager that contains the ListField and the Button.  The Manager will have to position the Button within its 'extent'.  I suspect this is possible, the concern I have is that focus might be an issue. 

 

To help you create your own manager, look here:

 

http://supportforums.blackberry.com/t5/Java-Development/How-to-Extend-Manager/ta-p/446749

http://supportforums.blackberry.com/t5/Java-Development/Create-a-custom-layout-manager-for-a-screen/...

 

You might also find the NegativeMarginsManager here, useful reading too:

 

http://supportforums.blackberry.com/t5/Java-Development/Implement-advanced-buttons-fields-and-manage...

 

I suggest you work on creating a standalone test version of this - i.e. a simple screen that uses this Manager and populates the ListField and processes the Button.  If you create something that is standalone and you want some assistance, then you can easily post your code, and we will try to help.

Developer
Posts: 19,616
Registered: ‎07-14-2008
My Device: Not Specified

Re: Adding static button in a Scrollable list

Thought I would have a play with this, took a little longer than I expected and there are some 'curve balls'.

 

Anyway, here is some code that might do what you want.  There are a few tricks in there, but see how you get on reviewing the code and the doc and the KB articles I pointed you at, to see if you can figure out what is going on.

 

Tested in OS 6.0 9800 Simulator, not on anything else. 

 

package mypackage;

import java.util.Vector;

import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.ScrollChangeListener;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.component.Status;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;

public class StaticButtonTestScreen extends MainScreen implements ListFieldCallback{

	private static int NUMBER_OF_ROWS_TO_ADD = 50;
	private static int NUMBER_OF_COLUMNS_TO_DISPLAY = 6;

	private Vector _listElements = new Vector();
	// We use a pretty crude method to supply the items to be displayed
	private ListField _listField;
	private int _requiredColumnWidth;
	
	StaticButtonTestScreen(){

		//! how wide will we make the columns?
		Font ourFont = this.getFont();
		_requiredColumnWidth = ourFont.getAdvance(" column 8 ");
		//! this example has fixed column widths.  They do not have to be.  Fixed is just simple to demonstrate.

		this.add(new LabelField("Above ListField", LabelField.FOCUSABLE));
		this.add(new SeparatorField());
		//! Add the ListField to a HorizontalFieldMaanger that can scroll horizontally.
		//! It is this that does the scrolling for us.
		StaticButtonManager myMan = new StaticButtonManager();

		//! Note the overridden methods in our ListField.
		_listField = new ListField() {
			//! OVerride layout so that you get the ListField defined the width that you want.
			protected void layout(int maxWidth, int maxHeight) {
				int requiredWidth = Math.min(maxWidth, this.getPreferredWidth());
				super.layout(requiredWidth, maxHeight);
			}
		};
		VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLLBAR | Manager.VERTICAL_SCROLL);
		// Put ListField in here so that it scrolls
		_listField.setCallback(this);
		_listField.setSize(NUMBER_OF_ROWS_TO_ADD);
		// setSearchable(true) so a key stroke will invoke indexOfList().  Try it
		_listField.setSearchable(true);
		for(int count = 0; count < NUMBER_OF_ROWS_TO_ADD; ++count) {
			String listItem = Integer.toString(count) + ".";
			_listElements.insertElementAt(listItem, count);
      }
		vfm.add(_listField);
		myMan.add(vfm);
		ButtonField bf = new SpecialButtonField("test");
		myMan.add(bf);
		this.add(myMan);
		this.add(new SeparatorField());
		this.add(new LabelField("Below ListField", LabelField.FOCUSABLE));
	}

	// Following methods are required by the ListFieldCallback interface

	public void drawListRow(ListField listField, Graphics graphics, int index, int y, int width) {

		int columnWidth = width/NUMBER_OF_COLUMNS_TO_DISPLAY;
		//! Use the width that we have, not the width we requested.
		//! There is a chance that they might be different, though I suspect this would only
		//! be seen during development when perhaps changes have not be made consistently. 
		   
		int xpos = 0;

		// First column test data supplied from program
		String suppliedData = (String) this.get(listField, index);
		graphics.setColor(Color.BLACK);
		graphics.drawText(suppliedData, xpos, y);
		xpos +=  columnWidth;

		// Dummy up the other columns.....
		graphics.setColor(Color.RED); 
		for ( int i = 1; i < NUMBER_OF_COLUMNS_TO_DISPLAY; i++ ) {
			graphics.drawText("c" + Integer.toString(i), xpos, y);
			xpos +=  columnWidth;
		}

	}

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

	//! In theory, the "framework" can call this, so it should return the same 
	//! value as the overridden getPreferredWidth().  But my testing suggests this is 
	//! is actually never called.  But for consistency, set it correctly!
	public int getPreferredWidth(ListField litfield) {
		return _requiredColumnWidth * NUMBER_OF_COLUMNS_TO_DISPLAY;
	}

	// People don't know how to use this, so I'm coding this up as an example
	// In the sample code you can use the digits to find things...
	public int indexOfList(ListField listField, String prefix, int start) {
		// Search from where we currently are forward.
		for ( int i = start; i < _listElements.size(); i++ ) {
			String element = (String) this.get(listField, i);
			if ( element != null && prefix != null ) {
				// Just being careful
				if ( element.startsWith(prefix) ) {
					return i;
				}
			}
		}
		// Not found, search from beginning to where we are currently
		for ( int i = 0; i < start; i++ ) {
			String element = (String) this.get(listField, i);
			if ( element != null && prefix != null ) {
				// Just being careful
				if ( element.startsWith(prefix) ) {
					return i;
				}
			}
		}
		// Didn't find it, don't move....
		return start;
	}

// Special Manager so that we can overlay the Fields
// and because the standard optimised paint does not
// cope with this, we need to invalidate() the Field on scroll to get
// it repainted.

// We also have a bit of work around

class StaticButtonManager extends Manager implements ScrollChangeListener {
	// Implement ScrollChangeListener so tha on a scroll, we repaint
	// because the default action is optimised and does not cope
	// with the overlaid Fields.  
	boolean scrollListenerSet = false;
	SpecialButtonField bf = null;
	XYRect ourExtent = new XYRect();
	public StaticButtonManager() {
		super(Manager.NO_VERTICAL_SCROLL | Manager.USE_ALL_HEIGHT);
	}
	// Override paintBackground just so we can see the extent of this Manager
	// Not necessary, just done to make it easier to see.  
	public void paintBackground(Graphics g) {
		int currentBackgroundColor = g.getBackgroundColor();
		try {
			g.setBackgroundColor(0X00CCCCCC);
			g.clear();
		} finally {
			g.setBackgroundColor(currentBackgroundColor);
		}
	}
	// Only expect two Fields
	// 1) A VFM which will scroll to handle the ListField
	// 2) A button that we will stuck at the bottom right
	protected void sublayout(int maxWidth, int maxHeight) {
		maxHeight = Display.getHeight()/2;
		// Set the Height that the ListField will use when scrolling.  
		if ( this.getFieldCount() != 2 ) {
			throw new RuntimeException("Incorrect number of Fields added");
		}
		VerticalFieldManager listFieldManager = (VerticalFieldManager) this.getField(0);
		if ( !scrollListenerSet ) {
			scrollListenerSet = true;
			listFieldManager.setScrollListener(this);
		}
		super.layoutChild(listFieldManager, maxWidth, maxHeight);
		super.setPositionChild(listFieldManager, 0, 0);
		if ( listFieldManager.getHeight() < maxHeight ) {
			maxHeight = listFieldManager.getHeight();
		}
		bf = (SpecialButtonField) this.getField(1);
		super.layoutChild(bf, maxWidth, maxHeight);
		super.setPositionChild(bf, maxWidth - bf.getWidth(), maxHeight - bf.getHeight());
		setExtent(maxWidth, maxHeight);
		
	}
	public void scrollChanged(Manager manager, int newHorizontalScroll, int newVerticalScroll) {
		this.invalidate(); // repaint everything....
	}
	/*
	 * Might be needed, comment out code just in case
	public int getFieldAtLocation(int x, int y) {
		if ( x >= this.getWidth() - bf.getWidth() &&
			 y >= this.getHeight() - bf.getHeight() ) {
			return 1;
		}
		return super.getFieldAtLocation(x, y);
	}
	*/
	// Just used to allow the user to use the trackpad to go horizontally and select the button.
	// Not really needed
	protected boolean navigationMovement(int dx, int dy, int status, int time) {
		boolean buttonInFocus = bf.isFocus();
		if ( dx > 0 && !buttonInFocus ) {
			bf.setFocus();
			return true;
		} else
		if ( dx < 0 && buttonInFocus ) {
			this.getField(0).setFocus();
			return true;
		}
		return super.navigationMovement(dx, dy, status, time);
	}
	// Because the Button keeps moving in relation t the manager
	// and the manager does not expect this,
	// We have to check the touch location ourselves
    protected boolean touchEvent(TouchEvent message) {
        int x = message.getX( 1 );
        int y = message.getY( 1 );
        getExtent(ourExtent);
        if( x < 0 || y < 0 || x > ourExtent.width || y > ourExtent.height ) {
                // Outside the field
                return false;
        }
		if ( x >= ourExtent.width - bf.getWidth() &&
		     y >= ourExtent.height - bf.getHeight() ) {
			bf.onClick();
			return true;
		}
        return false;
    }
}
// Special Button so that the Button can be clicked from the 
// Manager's touchEvent
class SpecialButtonField extends ButtonField {
	public SpecialButtonField(String label) {
		super(label);
	}
    protected boolean navigationClick( int status, int time ) {
    	onClick();
		return true;    
    }
    public void onClick() {
    	Status.show("Clicked: " + Integer.toString(_listField.getSelectedIndex()));
    }
    
}


}

 

Trusted Contributor
Posts: 145
Registered: ‎01-23-2012
My Device: 9300
My Carrier: airtel

Re: Adding static button in a Scrollable list

Hi Peter

 

 i need to add manager with background image in list row as i shown the screen shot.

 

 please can you tell me how to add the manager in drawListRow in your code .

 

thanks.

Developer
Posts: 19,616
Registered: ‎07-14-2008
My Device: Not Specified

Re: Adding static button in a Scrollable list

[ Edited ]

I presume by background image you mean the pictures to the left of your text in each ListField row.

 

This is a different problem to the one you were asking about initially, so please raise this in a new Thread.

 

As a quick answer, in general, you 'paint' whatever you want in the row in the drawListRow(..) method for your ListField.  So normally the code to do this will be included in that method.  You will paint the image, then paint the text to the right of the image. 

 

But be aware that in the sample code I provided, the fact that there is a ListField being displayed is not actually relevant.  The button would be positioned on the bottom right of whatever was in the VerticalFieldManager.  In this case it happens to be a ListField, since that is what you asked about. 

 

Also be aware that the code provided is sample code only, and is not really production code.  So you need to review the code to make sure you understand it, and then make sure that it works for you.  Please do not just cut and paste this code into your application.  If it breaks, you will need to be able to fix it so you had better understand it. 

 

One of the things I would definitely change is to have one add method for this Manager that adds both the VFM and SpecialButtonField at the same time.  The code assumes the user will add these correctly which is dangerous and not clear. 

Trusted Contributor
Posts: 145
Registered: ‎01-23-2012
My Device: 9300
My Carrier: airtel

Re: Adding static button in a Scrollable list

Thanks peter_strange for giving such a wonderful idea.

Developer
Posts: 19,616
Registered: ‎07-14-2008
My Device: Not Specified

Re: Adding static button in a Scrollable list

Glad to be of help.

 

Just to say that there are number of other things I would like to do to this sample code to tighten it up, including tailoring the invalidate down to just the area that needs to be repainted and producing a more generic version that will work with any VerticalFieldManager.  But I don't need this code, so there is no need for me to do it except as an exercise (and I have real work!).  But if you have an issue with this code, please come back and I will see what I can do. 

Trusted Contributor
Posts: 145
Registered: ‎01-23-2012
My Device: 9300
My Carrier: airtel

Re: Adding static button in a Scrollable list

Hi Peter_starange,

 

Thanks for your response. Definitely  i will come back if any issue's occur.