I have created a CustomTextField which scrolls itself towards left when i type text which are extra than the width of the TextField for which a HorizonalFieldManager is u
So, in BlackBerry fields, the extent is the actual visual size of a field. But, the virtual extent is the logical size it can use, some of which may not be visible. For Managers
that you want to have scroll, you would normally set the virtual extent to be larger than the extent.
I used this concept to dynamically change the virtual extent of your HorizontalFieldManager
, based on how much space was currently needed to just barely fit the text in the BasicEditField
. To do this, I had to let the HorizontalFieldManager
listen for changes to the BasicEditField
, by implementing FieldChangeListener
. Then, as each character is typed into the edit field, the horizontal field manager will recalculate how much width is needed for the amount of text that's now in the field. It then re-sets the virtual width to that width.
This causes the horizontal field manager to only allow scrolling to the end of the text entered, not way to the right, which is how the code originally worked.
So, I don't think the BlackBerry was doing anything wrong ... no bug in the OS. Previously, the virtual extent just wasn't set.
I split your HorizontalFieldManager into a new private class, because I don't like using anonymous classes when the logic exceeds about 5 lines of code. So, the solution below looks a little different.
Other thoughts:
1) There are drawing artifacts as a result of your attempt to draw a border with a custom paint()
implementation. But, that bug was originally there, and I interpretted this question to be about the scrolling problem. It looks like you were trying to use Border
objects, which is probably the better way to achieve a border for a scrolling field.
2) With my new solution, the actual CustomTextField
class doesn't have much in it. It's just a container (Manager
) for the CustomHorizontalFieldManager
. You could probably get rid of that outer layer if you wanted. But, I know that sometimes when you post code, you remove details that aren't important to the thing you're having trouble with. So, maybe having a VerticalFieldManager
contain a HorizontalFieldManager
which contains a BasicEditField
is needed. I'll leave that to you ... it would only be optional cleanup, though.
3) I tested this on a 5.0 Storm2 simulator.
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.util.Arrays;
public class CustomTextField extends VerticalFieldManager {
private int textWidth = 0;
private int textHeight = 0;
private CustomHorizontalFieldManager hfm;
public CustomTextField(int width, int height) {
super();
textWidth = width;
textHeight = height;
hfm = new CustomHorizontalFieldManager();
add(hfm);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(textWidth, textHeight);
setExtent(textWidth, textHeight);
}
protected void paint(Graphics graphics) {
// TODO: change me!
super.paint(graphics);
graphics.setColor(Color.BLACK);
graphics.drawRect(0, 0, textWidth, textHeight);
}
private class CustomHorizontalFieldManager extends HorizontalFieldManager implements FieldChangeListener {
private BasicEditField basicEditField;
/** the maximum virtual width of the edit field, based on the max num of chars */
private int maxVirtualWidth;
public CustomHorizontalFieldManager() {
super(Manager.HORIZONTAL_SCROLL);
int maxNumChars = 200;
basicEditField = new BasicEditField("", "", maxNumChars, BasicEditField.NO_NEWLINE);
// determine how wide the field would need to be to hold 'maxNumChars', with the font
// in use ... just pick a long string of all W's, since that's usually the widest char
char[] buffer = new char[maxNumChars];
Arrays.fill(buffer, 'W');
String spacer = new String(buffer);
maxVirtualWidth = basicEditField.getFont().getAdvance(spacer);
// we need to listen as the user types in this field, so we can dynamically alter its
// virtual width
basicEditField.setChangeListener(this);
add(basicEditField);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(maxWidth, maxHeight);
// extent is the visible size, virtual extent can be wider if we want scrolling
setExtent(textWidth, textHeight);
setVirtualExtent(maxVirtualWidth, textHeight);
}
public void fieldChanged(Field f, int context) {
if (f == basicEditField) {
// recalculate how much virtual width the edit field needs, based on the
// current text content
int newWidth = basicEditField.getFont().getAdvance(basicEditField.getText());
setVirtualExtent(newWidth, textHeight);
}
}
}
}