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
Highlighted
New Developer
Posts: 10
Registered: ‎11-16-2009
My Device: Not Specified
Accepted Solution

Release Field Focus

I have RichText field inside a VerticalFieldManager.  This VFM takes up only a few lines.  I have two of these on the screen.  When I scroll using the thumb wheel it starts with the top most VFM manager and scrolls all the way to the bottom of the text in the top most VFM text field before moving the the bottom VFM Textbox.  Since the text fields can have a large amount of text in them it takes a long time to scroll through all the text in the top VFM before going to the bottom one.  I'd like to take over navigationMovement and if the textbox hasn't been clicked then just move on to the next textbox.  The user can then move between the two and click on which ever one he/she wants to read by clicking on it.  I need to be able to give up selection or focus inside navigationMovement.  I tried focusRelease and setFocus.  Maybe I need to do this on the screen rather than the VFM.

 

Any help would be greatly appreciated.  I can post sample code if it would help.

 

Thanks in advance.

New Developer
Posts: 10
Registered: ‎11-16-2009
My Device: Not Specified

Re: Release Field Focus

This is what I have so far.  If I take over navigationMovement on the MainScreen and call setFocus on the next field then all is well and the trackball up and down moves between the field managers great, bypassing RichText fields without scrolling through all their text.

 

    protected boolean navigationMovement(
                              int dx, int dy, int status, int time)
    {
        for (int i = 0;  i < getFieldCount();  i++)
        {
            Field       field   =   getField(i);
            if   (field.isFocus() == true)
            {
                // get object for next field in focus order
                field = (i == (getFieldCount() - 1)) ? 
                               getField(0) : getField(i + 1);

                // advance focus to next field
                field.setFocus();
                break;
            }
        }
        return  false;
    }

 

 

 

New Developer
Posts: 10
Registered: ‎11-16-2009
My Device: Not Specified

Re: Release Field Focus

Now that I have focus skipping over very lengthy RichText fields held in VirticalFieldManagers I'd like to implement click on one of them and allow scroll.  So this is what I coded on the VirtualFieldManager. 

 

protected boolean navigationClick(int status, int time)
{
    m_bScrollEnabled = m_bScrollEnabled == true ? false : true;
    return  false;
}
    
protected boolean navigationMovement(
                      int dx, int dy, int status, int time)
{
    if  (m_bScrollEnabled == true)
    {
        int     i_scrolloff =   (m_iCurrentLine + dy) * m_iFontHeight;
        if  (i_scrolloff < 0 || 
                 (i_scrolloff + getVisibleHeight()) > getVirtualHeight())
            return  true;       //  we're at the beginning or end
                
        m_iCurrentLine      +=  dy;
        setVerticalScroll(i_scrolloff);
        return true;
    }
    else
    {
        return false;
    }
 }

 

This works great and allow the scroll to work well inside the RichText field.  Now I want to put the above post together with this bottom solution.  I change the navigationMovement on the screen to call the nativagtionMovement on each field and if the field.navigationMovement comes back false then I assume I should process the event.  If it comes back false then I want to move focus to the next field.

 

protected boolean navigationMovement(
                      int dx, int dy, int status, int time)
{
    for (int i = 0;  i < getFieldCount();  i++)
    {
        Field       field   =   getField(i);
        if   (field.isFocus() == true)
        {
            if (super.navigationMovement(dx, dy, status, time) == false)
            {
                field = (i == (getFieldCount() - 1)) 
                          ? getField(0) : getField(i + 1);
                field.setFocus();
                break;
            }
            else
                return  true;
        }
    }
    return  false;
 }

 

The problem is super.navigationMovement comes back true always.  Even If my VFM navigationMovement returns false.  I tried putting a navigationMovement on the RichText field in the VFM and return false but this didn't help either.

 

Can anyone enlighten me to how the control flow goes here.  Why does the screen get the first navigationMovement event and I have to call super.navgationMovement to go up the chain.  Shouldn't the top most control get the navigationMovement event first the super calls down the chain.  I missing something very fundamental here.

 

Thanks.

 

New Developer
Posts: 10
Registered: ‎11-16-2009
My Device: Not Specified

Re: Release Field Focus

[ Edited ]

 

protected boolean navigationMovement(int dx, int dy, int status, int time)
    {
        if  (m_bScrollEnabled == true)
        {
            int     i_scrolloff =   (m_iCurrentLine + dy) * m_iFontHeight;
            if  (i_scrolloff < 0 || (i_scrolloff + getVisibleHeight()) > getVirtualHeight())
                return  true;       //  Eat the scroll event cause we're at the beginning or end
                
            m_iCurrentLine      +=  dy;
            setVerticalScroll(i_scrolloff);
            return  true;
        }
        else
        {
            Screen  scr         =   getScreen();
            int     i           =   scr.getFieldWithFocusIndex();
            Field   field       =   (i == (scr.getFieldCount() - 1)) ? scr.getField(0) : scr.getField(i + 1);           
            field.setFocus();
        }
        return  false;
    }

 

Rather than placing the setFocus on the Screen.navigationMovement I placed it on the VerticalFieldManager.navigationMovement and requested the VFM screen object.  This way I'm not reliant on the navigationMovement to return true or false.  (Wish I new why that wasn't working though).  Now this lead to a problem saving the location within the RichText field.  I scroll through the RIchText then setFocus to another field then setFocus back to the RIchText field and it sets the VerticalScroll to 0 instead of leaving it where it was.  

 

The above code allows for moving focus between fields even though some of those fields could be RichText Fields with large amount of data.  Scrolling in a particular RichText field is done by clicking on it and then I can scroll though the text.  The problem I have with this approach is setVerticalScroll doesn't work in the onFocus method.  What probably is happening is the setVerticalScroll gets set to 0 when field.setFocus is called.  I think the problem may be that this setting of the VerticalScroll to 0 gets done after the onFocus method.  If I put the setVerticalScroll somewhere else like say, trackwheelclick then its works fine and scrolls the RichText to the last location I was reading.

 

I need a way of setting setVerticalScroll upon focus.  I wish there was a way to look under the hood here.  I'd like to know exactly how these events are getting called and in what order.  Is there any documentation on the framework?

 

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

Re: Release Field Focus

I've been watching this Thread with interest, you are doing well!

 

Just a thought with respect to setting VerticalScroll. 

 

In your onFocus, you could try doing

UiApplication.getUiApplication.invokeLater(new Runnable() {

public void run() {

vfm.setVerticalScroll(nnn);

}

});

 

Basically this may allow the framework processing to complete, then do your setVerticalScroll.  It is a bit of a kludge, it would be nicer to know when you can actually do this, but it might work.  Might not as well.  Let us know.

New Developer
Posts: 10
Registered: ‎11-16-2009
My Device: Not Specified

Re: Release Field Focus

Peter thank you for your contribution.

 

I placed the invokelater in the onfocus method and it in fact works quite well.

 

This is my first java program and first blackberry application so I'm sure I don't always take the straightest path.

 

I'm still trying to get use to the memory mgmt model.  I can new the Runnable thread in the onFocus event?  It runs just once and I don't have to worry and memory fragmentation of leaks?  Also not sure how the run() method actually gets my VFM 'this->' pointer but it does.  Its like magic.

 

Anyhow I'm going to accept this as a solution, I'm going to thank you again and I'm going to post the three methods that I have placed on my VerticalFieldManager which contains a single RichText field.

 

Maybe someone else is having problems with the setVerticalScroll not taking effect.

 

 

    protected void onFocus(int direction)
    {
        super.onFocus(direction);

        //  Need to call setVerticalScroll a little later.  It looks like
        //  setFocus is overriding it.  If we call it later then it will
        //  actually take effect.
        UiApplication.getUiApplication().invokeLater(
            new Runnable()  {
                public void run()   {
                    setVerticalScroll(m_iCurrentLine * m_iFontHeight);
                }
            });
    }
 
    protected boolean navigationClick(int status, int time)
    {
        m_bScrollEnabled = m_bScrollEnabled == true ? false : true;
        return  true;
    }
    
    protected boolean navigationMovement(int dx, int dy, int status, int time)
    {
        if  (m_bScrollEnabled == true)
        {
            int     i_scrolloff =   (m_iCurrentLine + dy) * m_iFontHeight;
            if  (i_scrolloff < 0 || (i_scrolloff + getVisibleHeight()) > getVirtualHeight())
                return  true;       //  Eat the scroll event cause we're at the beginning or end
                
            m_iCurrentLine      +=  dy;
            setVerticalScroll(i_scrolloff);
            return  true;
        }
        else
        {
            //  If here then RichText field is not selected
            //  figure out which field currently has focus
            //  and move focus to next field
            Screen  scr         =   getScreen();
            int     i           =   scr.getFieldWithFocusIndex();
            Field   field       =   (i == (scr.getFieldCount() - 1)) ? scr.getField(0) : scr.getField(i + 1);
            field.setFocus();
        }
        return  false;
    }