Android Question Virtual Keyboard hides input fields in webview

Martin Larsen

Active Member
Licensed User
Longtime User
I have a problem with the soft keyboard hiding input fields in webviews. I have tried the solution in this post but it works "too well" so to speak. It always pushes the webview up, thus hiding fields in the top that would not normally be covered by the keyboard.

I have attached an example loading the Register page from this forum.

It works fine for the email and password fields. The webview is pushed upwards so you can see the fields while entering. However, the username fields is pushed out of sight as shown on screenshot #2.

How can this problem be solved?

screenshot-2020-02-18_10.06.25.473.png
screenshot-2020-02-18_10.06.36.767.png
 

Attachments

  • webview.zip
    8.9 KB · Views: 390

JohnC

Expert
Licensed User
Longtime User
There is not a lot you can do because webview always tries to make sure that whatever input item that currently has "focus" is clearly visible in webview.

And in this case it looks like the focus is on the captcha checkbox and that is why it shifted up the page so make sure that the entire captcha item is visible. Because if the captcha checkbox is suppose to have focus, but the form was shifted any lower (to make the "Email" editextbox fully visible), then the keyboard will be chopping off the bottom of the captcha checkbox.

To access the Email field, the user would simply scroll the page down until it is visible.

Also, keep in mind that other devices with different size screens and/or DPI might be able to very well display the entire form even when the keyboard is shown because those devices have a larger screen.

This shifting up of the page "functionality" is by design to make sure that all devices can access all fields of a form when the keyboard is displayed.
 
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
I examined it further and I don't think it has anything to do with what field has the focus. I just choose the register page as an example, it happens on all pages with text input fields.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Use webviewextras and run some javascript to force webview to scroll to the top of the page when you need it to..

First add the chromeclient and enable javascript in webview:
B4X:
wve.addWebChromeClient(wv, "WVE")
wv.JavaScriptEnabled = True

Then you can inject/run the below javascript anytime you need the page to scroll to the top:
B4X:
wve.executeJavascript(wv, "window.scrollTo(0, 0);"

For example, you can run the above javascript the first time the keyboard is shown on a particular page. NOTE: You don't want to run this code EVERY time the keyboard is shown on the same page because the user could be working on a text field at the bottom of the page and you don't want the page to suddenly jump to the top when the keyboard appears because it will annoy the user. So, just use the code when it's appropriate.
 
Last edited:
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
I have thought of something similar. The main problem is to know when to scroll the page or change the height of webview. I am experimenting with a callback from the webpage when an input field gets the focus.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
I might be misunderstanding your issue, but please keep in mind that webview will *automatically* scroll the page to make sure that the input item is visible even when the keyboard is displayed (if you are managing the size of webview properly).

So, I guess my next question is how are you resizing webview when the keyboard appears and disappears?

It should be similar to this:
B4X:
Sub IME_HeightChanged(NewHeight As Int, OldHeight As Int)
    wv.Height = NewHeight
End Sub

(the above code assumes that webview is full screen)

Basically, you should NOT be modifying the .Top property of webview, but instead modify the height of webview depending on if the keyboard is displayed or not. This way when webview gets "crushed" it will allow scrolling the page up or down to make sure the desired input field can be made displayed even in the reduce vertical window space when the keyboard is showing.
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Ok, I just took at look at your code and figured out what is wrong.

First, you might want to use the anchors more efficiently for the webview by setting both anchors to full horizontal and full vertical (right now you are only anchoring left and top) and remove the below two lines from the "General Script" (Your code does the same thing, but anchors make it so much easier to do it):

B4X:
WebView1.SetLeftAndRight(0%x,100%x)
WebView1.SetTopAndBottom(0%y,100%y)

Second, change the IME_HeightChanged code to this:
B4X:
Sub IME_HeightChanged(NewHeight As Int, OldHeight As Int)
    WebView1.Height = NewHeight
End Sub
 
Last edited:
Upvote 0

Martin Larsen

Active Member
Licensed User
Longtime User
First, you might want to use the anchors more efficiently for the webview by setting both anchors to full horizontal and full vertical

I must admit that I just modified one of the example apps in the B4A folder! I didn't even look at the layout :)
That said,I really like designer scripts but in this case I fully agree: using anchors is much more straightforward.

Second, change the IME_Height code to this:

Wow, that was simple! I was taking the code from Erel's post thinking that it would apply to a webview too. But alas, no!

I was beginning to think I had to go the javascript way with a callback to a B4A function to calculate the new position! Actually, just before your nice post I ended up with this line of Javascript:

B4X:
($(window).height() - $("input").offset().top - $("input").outerHeight(true) + $(window).scrollTop()) / $(window).height()

This calculates the bottom of the input field as a fraction of the total height of the webview which can then be used to adjust the new TOP.

Thankfully I didn't get to implement it in B4A before you post arrived. Your solution is so much simpler and better!

Thanks!
 
Upvote 0
Top