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
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified
Accepted Solution

ListField that scrolls Horizontally

I have, over the years, had a number of goes at a horizontally scrolling ListField.

 

I have finally managed to create one that I think works properly.  And as you might expect, it was not actually that difficult, just took the odd tweak...

 

I have pasted below a sample Screen that includes a horizontally scrolling ListField.  The important comments are on the lines marked with

//!

 

Hopefully this example will help other people,trying to achieve this.  Or just provide an example of using ListField. 

 

Please report any bugs, suspect code or ask any questions about how this works here.

 

Hope it works for you...

 

You might find the attached source easier to use.

 

//! see comment lines starting with "//!"
//! for important points regarding this.

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.XYRect;
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.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;

public class HorizontalScrollTestScreen  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;
	
	HorizontalScrollTestScreen(){

		//! how wide will we make the columns?
		_requiredColumnWidth = this.getFont().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.
		HorizontalFieldManager hfm = new HorizontalFieldManager(Manager.HORIZONTAL_SCROLL|Manager.HORIZONTAL_SCROLLBAR) {
			// 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);
				}
			}
		};
		//! 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);
			}
			//! Override getFocusRect otherwise the scroll up or down the LisstField will move the
			//! focus back to the beginning of the row.  
			//! Remove this and see what happens.  
			public void getFocusRect(XYRect focusRect) {
				super.getFocusRect(focusRect);
				focusRect.x = this.getManager().getHorizontalScroll();
				focusRect.width = Math.min(Display.getWidth(), this.getWidth() - focusRect.x);
			}
			//! Use getPreferredWidth() to set the required width.
			//! In fact, in my testing, this method is ONLY called from our
			//! layout method, though the "framework" can, in theory,
			//! call getPreferredWidth() whenever it wants.  
			public int getPreferredWidth() {
				return _requiredColumnWidth * NUMBER_OF_COLUMNS_TO_DISPLAY;
			}
		};
		_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);
        }
		hfm.add(_listField);
		this.add(hfm);
		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("column" + 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;
	}

}

 

 

 

Please use plain text.
Developer
ravi1989
Posts: 777
Registered: ‎07-21-2012
My Device: 9810
My Carrier: 0

Re: ListField that scrolls Horizontally

The code is note working in 9700 simulator..

have you check this code..

Please use plain text.
Developer
paulkayuk
Posts: 133
Registered: ‎04-30-2010
My Device: Curve 8520
My Carrier: T-Mobile

Re: ListField that scrolls Horizontally

@ravi1989 I'm sure it would be helpful to Peter if you could provide him with a bit more detail than a bland 'The code is not working in 9700 simulator'  e.g. have you attempted to step through the code with breakpoints to determine where in the code the problem occurs?

Please use plain text.
Developer
ravi1989
Posts: 777
Registered: ‎07-21-2012
My Device: 9810
My Carrier: 0

Re: ListField that scrolls Horizontally

Actually code is running successfully and list is display ..but when i press trackpad horizontally it list is not moving horizontally (mean scrolling)..i think i need to do code in this function

 

 

protected boolean navigationMovement(int dx, int dy, int status, int time) {

if(dx>0){


this.getManager().getHorizontalScroll();

focusAdd(true);
}
return true;
};

 

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: ListField that scrolls Horizontally

I have not tested this in a 9700 SImulator but I have tested in a 9780. 

 

I have found that some of the Simulators behave a little differently regarding trackpad interaction.  Hold your mouse over the trackpad, press and hold the left mouse button and then move the mouse left and right.  The trackpad should show an indication that it is active and the direction you are moving.  And the ListField will scroll, provided it is in focus of course..

 

There should be no need to override navigationMovement - this interaction is managed by the HFM. 

 

If you continue to have problems please try another SImualtor - or try a touchscreen Simulator and just use the trackpad. 

 

If you still have problems, then let me know the details of the Simualtor that you are having problems with.  I will try to download and test. 

 

And thanks for the input paulkayuk, "not working" is not a very useful problem description!

Please use plain text.
Developer
ravi1989
Posts: 777
Registered: ‎07-21-2012
My Device: 9810
My Carrier: 0

Re: ListField that scrolls Horizontally

I also check on 8520 it is not working...:smileysad:  please run this code ..

package com.black.applicationloader;

//! see comment lines starting with "//!"
//! for important points regarding this.

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.XYRect;
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.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;

public class HorizontalScrollTestScreen  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;
	
	HorizontalScrollTestScreen(){

		//! how wide will we make the columns?
		_requiredColumnWidth = this.getFont().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.
		HorizontalFieldManager hfm = new HorizontalFieldManager(Manager.HORIZONTAL_SCROLL|Manager.HORIZONTAL_SCROLLBAR) {
			// 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);
				}
			}
		};
		//! 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);
			}
			//! Override getFocusRect otherwise the scroll up or down the LisstField will move the
			//! focus back to the beginning of the row.  
			//! Remove this and see what happens.  
			public void getFocusRect(XYRect focusRect) {
				super.getFocusRect(focusRect);
				focusRect.x = this.getManager().getHorizontalScroll();
				focusRect.width = Math.min(Display.getWidth(), this.getWidth() - focusRect.x);
			}
			//! Use getPreferredWidth() to set the required width.
			//! In fact, in my testing, this method is ONLY called from our
			//! layout method, though the "framework" can, in theory,
			//! call getPreferredWidth() whenever it wants.  
			public int getPreferredWidth() {
				return _requiredColumnWidth * NUMBER_OF_COLUMNS_TO_DISPLAY;
			}
			
			
			
		};
		_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);
      }
		hfm.add(_listField);
		this.add(hfm);
		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("column" + 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;
	}

}
Please use plain text.
Developer
ravi1989
Posts: 777
Registered: ‎07-21-2012
My Device: 9810
My Carrier: 0

Re: ListField that scrolls Horizontally

Hello i under stand this code is working on 9800 ..touch device ..but this code is not working on non touch device..

 

can it is possible to make for non touch device...

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: ListField that scrolls Horizontally

You are correct, this does not run on an 8520 - I will investigate.

 

Just for next time, what is the point of pasting the code - you could just have put a link to my post?

 

Can you please test on a non touchscreen Simulator that is running OS 6.0 or higher and see if you see the same problem? 

Please use plain text.
Developer
ravi1989
Posts: 777
Registered: ‎07-21-2012
My Device: 9810
My Carrier: 0

Re: ListField that scrolls Horizontally

No ...9800 it is working...on touch device it is fine .but i need for non touch device...

Please use plain text.
Developer
peter_strange
Posts: 19,601
Registered: ‎07-14-2008
My Device: Not Specified

Re: ListField that scrolls Horizontally

Can you please run this on a non touch screen device with an OS that is higher than OS 5.0.  Like the 9780, or 9320.  OK?

Please use plain text.