Horizontal Scrolling and TextField Error

2019-02-04 19:48发布

问题:

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 used But now the problem is if i Right click with my mouse and scroll it it goes on to inadequate length but does not stop to the last word i type What is the problem here ?? Is it a bug

I just need that to disable HorizontalScrolling when it reaches the last word It should be able to scroll just between the start and end of last word in word

Check out the code

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FocusChangeListener;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.XYRect;
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.ui.decor.Border;
import net.rim.device.api.ui.decor.BorderFactory;


public class CustomTextField extends VerticalFieldManager {
    private int textWidth=0;
    private int textHeight=0;
    private BasicEditField basicEditField;
    private HorizontalFieldManager hfm;
    //Border border;

    public CustomTextField(int width,int height) {
        super();
        textWidth=width;
        textHeight=height;
        //border=BorderFactory.createSimpleBorder(new XYEdges(1, 1, 1, 1)); 


        hfm=new HorizontalFieldManager(Manager.HORIZONTAL_SCROLL){
            protected void sublayout(int maxWidth, int maxHeight) {
                super.sublayout(maxWidth, maxHeight);
                setExtent(textWidth, textHeight);
            }
        };  
        basicEditField=new BasicEditField("","",200,BasicEditField.NO_NEWLINE);
        //basicEditField.setBorder(border);

        hfm.add(basicEditField);
        add(hfm);
    }


    protected void sublayout(int maxWidth, int maxHeight) {
        super.sublayout(textWidth, textHeight);
        setExtent(textWidth, textHeight);

    }


    protected void paint(Graphics graphics) {
        super.paint(graphics);
        graphics.setColor(Color.BLACK);
        graphics.drawRect(0,0, textWidth, textHeight);
    }

}

i have initialised it as

 CustomTextField textField=new CustomTextField(200, 20);
            add(textField);

I feel the need of Scroll(is Scrolling Function) for HorizontalFieldManager ... but have not yet came up to solution yet Please help

回答1:

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

}