iOS Question B4XFloatTextField keyboard hiding views.

davemorris

Active Member
Licensed User
Hi Guys

I am in the process of converting some old code to B4X using the new XUI views, in particular B4XFloatTextField.

I am now having problems with the keyboard hiding the views (hopefully it's something simple that I have missed).

I converted a form which used the older textField view to B4XFloatTextField and associated code.

To move the panel up (and prevent the keyboard covering the view) I used my original code below - it is fairly standard stuff - their are several posts in the forum discussing this method.


B4X:
' This method (and the IsFirstResponder() method, below) to ensure the keyboard doesn't cover the relevant
' textfield is taken from here: https://www.b4x.com/android/forum/threads/problem-hide-keyboard.47294/
Private Sub mPage_KeyboardStateChanged(oskHeight As Float)
    If oskHeight = 0 Then ' Keyboard has been hidden
        mPage.RootPanel.Top = 0
    Else ' Keyboard has been shown
        For Each pageView As View In mPage.RootPanel.GetAllViewsRecursive
            If IsFirstResponder(pageView) Then
                Dim viewBottom As Int = pageView.Top + pageView.Height ' This appears to be the problem pageView.Top = 0
                Dim keyboardTop As Int = mPage.RootPanel.Height - oskHeight
                Dim actualViewBottom As Int = viewBottom + mPage.RootPanel.Top
                Dim panelTopModifier As Int = mPage.RootPanel.Top - (oskHeight - (mPage.RootPanel.Height - viewBottom))
                If keyboardTop < actualViewBottom Then
                    mPage.RootPanel.Top = Min(0, panelTopModifier)
                End If
                Exit
            End If
        Next
    End If
End Sub

' This method (and the mPage_KeyboardStateChanged() method, above) to ensure the keyboard doesn't cover the relevant
'   textfield is taken from here: https://www.b4x.com/android/forum/threads/problem-hide-keyboard.47294/.
Private Sub IsFirstResponder(ntvObj As NativeObject) As Boolean

    Return ntvObj.RunMethod("isFirstResponder", Null).AsBoolean
End Sub

The problem appears to be about line 9 - it appears pageView.Top is always 0, not the property value for the view I created. However, it does work OK if you use B4XViews. I have tried several modules and they all appear to suffer from the same problem.

Sorry if my description is a bit scratchy, but before I generate some simple code showing an example I was hoping that someone could spot the issue.

Kind regards
Dave Morris
 

davemorris

Active Member
Licensed User
Hi Guys again.
Quick update - I have discovered that I am using an old version of XUI Views library (v2.25) just updated to the latest version v2.32.

Regards
Dave
 
Upvote 0

davemorris

Active Member
Licensed User
Hi, Erel - thanks for the quick reply

Try the latest version and it still did not work. I did a bit more work on previously working code and as soon as the view was changed to a B4XFloatTextField the Top property went to = 0 (see my first post code line #9) and keyboard covered the view.

Best of luck
Dave
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Upvote 0

davemorris

Active Member
Licensed User
Hi Erel - I am still having problems

I have tried to implement your suggestions for mPage_KeyboardStateChanged() sub, see below - is it correct?

Modified code:
' This method (and the IsFirstResponder() method, below) to ensure the keyboard doesn't cover the relevant
' textfield is taken from here: https://www.b4x.com/android/forum/threads/problem-hide-keyboard.47294/
Private Sub mPage_KeyboardStateChanged(oskHeight As Float)
    If oskHeight = 0 Then ' Keyboard has been hidden
        mPage.RootPanel.Top = 0
    Else ' Keyboard has been shown
        For Each pageView As B4XView In mPage.RootPanel.GetAllViewsRecursive
            If pageView.Tag Is B4XFloatTextField Then
                Dim x As B4XFloatTextField = pageView.Tag
                If IsFirstResponder(x.TextField) Then
                    Dim viewBottom As Int = x.TextField.Top + x.TextField.Height ' It appears .top is  = 0
                    Dim keyboardTop As Int = mPage.RootPanel.Height - oskHeight
                    Dim actualViewBottom As Int = viewBottom + mPage.RootPanel.Top
                    Dim panelTopModifier As Int = mPage.RootPanel.Top - (oskHeight - (mPage.RootPanel.Height - viewBottom))
                    If keyboardTop < actualViewBottom Then
                        mPage.RootPanel.Top = Min(0, panelTopModifier)
                    End If
                    Exit
                End If               
            End If
        Next
    End If
End Sub

Using debug and stepping thro and looking at line #11 - it will not let me view x.TextField.Top but the value for viewBottom = 49 suggests that x.TextField.Height is ok (actual value = 50) but x.TextField.Top is still = 0

Kind regards
Dave
 
Upvote 0

davemorris

Active Member
Licensed User
Hi Erel
Sorry I am a bit lost with your last post, I can't work out what is going on under the hood (perhaps I should look at the source file in the library for
B4XFloatTextField).

x.mBase I assume you are referring the the Base class - but that from inheritance so I am not sure.

Anyway, I changed line #11 as below

Code change in line #11:
' Original....
Dim viewBottom As Int = x.TextField.Top + x.TextField.Height ' It appears .top is  = 0

' Replaced with ....
Dim viewBottom As Int = pageView.Top + pageView.Height ' It appears .top is now providing a correct value (.height has always appeared correct)

That code change did work, but is it correct?

Kind regards
Dave
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
The simplest way to create a form: https://www.b4x.com/android/forum/t...esdialog-cross-platform-forms.103842/#content

I don't recommend modifying Page.RootPanel.Top. You should instead add a panel, anchored to all sides, and put all the fields inside it.

You can then use this code to push the panel (Panel1) when the keyboard is visible:
B4X:
Private Sub Page1_KeyboardStateChanged (Height As Float)
    Panel1.Top = 0
    If Height = 0 Then Return
    Sleep(0)
    For Each v As B4XView In Page1.RootPanel.GetAllViewsRecursive
        If v.Tag Is B4XFloatTextField Then
            Dim f As B4XFloatTextField = v.Tag
            If f.Focused Then
                Dim base As Panel = f.mBase
                Dim d As Double = base.CalcRelativeKeyboardHeight(Height)
                If d < base.Height Then
                    Panel1.Top = -(base.Height - d)
                End If
            End If
        End If
    Next
End Sub
 
Upvote 0

davemorris

Active Member
Licensed User
Hi, Erel - thanks the response.

Firstly, your code (for me anyway) appears more straight forward the my original offering and I will give it a try.

It is good to see you have dropped the IsFirstResponder - frankly never like using code which does things based on a underlying knowledge of the system - don't think that is what B4X is all about.

What I am getting to is, my original code is taken from a post which dates back to 2014 and there are many posts all over the forum talking about B4i keyboard problems. For example my keyboard is - "hiding the views", "not appearing when you want it" or the big one is "I want to only enter numbers - where is the done button?". I would be nice if a tutorial could be generated to discuss these and offer a solution we can all use it as a reference, as you have done with things like notifications. The problem with Forums is that important information can be hidden in the text.

Sorry to suggest more work, but whilst the Forum is good and the documentation is acceptable, I personally find the tutorials to be excellent and the more the better.

Very kind regards
Dave
 
Upvote 0
Top