B4A Library IME2 Library

I have been having a lot of trouble lately with layouts being corrupted when rotating a device with the soft keyboard open.

The problem stems from trying to use the IME library HeightChanged event. Unfortunately Android provides no direct way to determine whether the soft keyboard is shown or not so the IME.HeightChanged event uses a bit of a hack. to detect this. The problem that I have found is that, particularly when rotating a device with the keyboard is open, different soft keyboards and different devices produce different erroneous layouts after rotation, particularly in split mode. In some devices it works well, others produce poor results.

The IME2 library provides some extra methods to help sort this problem and the KeyboardTest app uses them to demonstrate obtaining the correct layout after device rotation with the keyboard open in all normal and split mode combinations in portrait and landscape. This app works on all my devices but may not work on yours.

Erel posted a different possible workaround here.
It is worth trying that first to see if it works for you but it didn't work for me in all circumstances - basically because you can get multiple spurious HeightChanged events during/after rotation and his solution just accepts the first one.

If anyone has something simpler to solve this problem I would welcome trying it.

From the XML for the IME2 library.

It is a strict superset of the original IME library but includes the following additional methods.

IsActive
IsAcceptingText
IsSplitMode
GetDisplayRectangle
GetKeyboardRectangle
GetWindowRectangle
ChangeKeyboard

IsActive is True if there are any editable views (such as EditText) inflated.

IsAcceptingText is True if an inflated editable view (such as EditText) has the focus.
It's possible for an editable view to have focus while the keyboard is not displayed.
For example having tapped on an EditText and then pressing Back to close the keyboard.

IsSplitMode returns True if the activity is running in split screen mode.
Many of these methods are not valid to use if the activity is running in split screen mode.
Those that are not valid in split screen mode are indicated in the method comment.
Unless absolutely necessary it is probably best to ignore HeightChanged events in split mode.

Inexplicably Android provides no direct way to determine whether the soft keyboard is shown or not.
GetKeyboardRectangle provides a way of determining whether it is shown or not without waiting for an event.
GetKeyboardRectangle compares the display size to the current window size in order to determine what
the size and location of the keyboard could be. Checking the height of this Rect is an alternative way
of determining if the keyboard is shown than comparing NewHeight and OldHeight in the HeightChanged event.
Note that although termed 'Height' the HeightChanged event parameters appear to actually be the Top value of the keyboard location.

GetDisplayRectangle gets the dimensions of the Display on which the activity is being drawn as a Rect.
These values are absolute pixel values, Left and Top are always 0.
When not in split screen mode these values reflect those of the full physical display of the device.
In split mode they define the size of a smaller logical display hosting the activity.

GetWindowRectangle gets the location and dimensions of the Activity's window as a Rect.
These values are absolute pixel values relative to the physical display screen.
They define the size and location on screen of the visible portion of the activity.

ChangeKeyboard shows the IME selection popup to select one of the input methods available to the system.
Invoking this allows a user to quickly select a keyboard.
 

Attachments

  • IME2_V1.00.zip
    20.5 KB · Views: 395

JohnC

Expert
Licensed User
I had a hunch when there wasn't a clean solution for your test app bug last week, that you might create a lib to fix it ;)
 

Star-Dust

Expert
Licensed User
The library is clean and just provides more information - but the HeightChanged event in B4A code that does the work is pretty gruesome :eek:
I don't understand much about Java, but I guess it depends on it being an old library. One of the first made. Today it would be done differently
 

agraham

Expert
Licensed User
I don't understand much about Java, but I guess it depends on it being an old library. One of the first made. Today it would be done differently
No it wouldn't, don't think I haven't tried to do it better. Android still sucks deeply in many respects and this is one of the most obvious.
 
Last edited:

agraham

Expert
Licensed User
At last !
It's only taken them twelve years since first release to correct this omission!
 

Star-Dust

Expert
Licensed User

agraham

Expert
Licensed User
I do wonder, though without any evidence to back it up, whether this is a sign of Microsoft influence on Android. Keyboard handling on the Surface Duo must have needed some changes and I know that Microsoft has been posting Android code changes to the repository. I have noticed that the MIcrosoft SwiftKey keyboard causes the worst of these layout problems and I assume that an enhanced version of it will be the default keyboard on Duo.
 

AnandGupta

Well-Known Member
Licensed User
I do wonder, though without any evidence to back it up, whether this is a sign of Microsoft influence on Android. Keyboard handling on the Surface Duo must have needed some changes and I know that Microsoft has been posting Android code changes to the repository. I have noticed that the MIcrosoft SwiftKey keyboard causes the worst of these layout problems and I assume that an enhanced version of it will be the default keyboard on Duo.
I think you are 100% right.

MS is better influencer than mere users.

Regards,

Anand
 

cxbs

Member
Licensed User
Hello agraham!

When set <item name="android:windowTranslucentStatus">true</item>
no work!

SetApplicationAttribute(android:theme, "@style/MyAppTheme")

CreateResource(values, theme.xml,
<resources>
<style name="MyAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#FFFFFF</item>
<item name="colorPrimaryDark">#007CF5</item>
<item name="colorAccent">#07c160</item>
<item name="android:colorControlNormal">#aaaaaa</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowLightStatusBar">true</item>

<item name="android:windowTranslucentStatus">true</item>

<item name="android:windowTranslucentNavigation">false</item>
<item name="android:fitsSystemWindows">true</item>
</style>
</resources>
)
 

alimanam3386

Active Member
Licensed User
I have been having a lot of trouble lately with layouts being corrupted when rotating a device with the soft keyboard open.

I am just trying to run your attached source code however I get this error ( B4A Ver 10.7 )

in Manifest :
B4X:
AddManifestText(<edtSource android:imeOptions="flagNoExtractUi|flagNoFullscreen" />)


The error when compiling :
B4X:
AndroidManifest.xml:14: error: unexpected element <edtSource> found in <manifest>.
 

agraham

Expert
Licensed User
They affect the behaviour of the IME in landscape mode. The important one is flagNoFullscreen which stops the IME throwing up it's own EditText for input in landscape mode and allows the original EditText to be edited - important in my BasicIDE code editor - and it did work before.

I added flagNoExtractUi as I found it used in someone else's solution to similar problems with the IME as I was having (probably on Stack Overflow) together with flagNoFullscreen but from the description below iit s probably superfluous. However I don't remember the "it may become deprecated in the future" comment when I was originally researching this!

EditorInfo | Android Developers

IME_FLAG_NO_EXTRACT_UI
Added in API level 3

public static final int IME_FLAG_NO_EXTRACT_UI
Flag of imeOptions: used to specify that the IME does not need to show its extracted text UI. For input methods that may be fullscreen, often when in landscape mode, this allows them to be smaller and let part of the application be shown behind, through transparent UI parts in the fullscreen IME. The part of the UI visible to the user may not be responsive to touch because the IME will receive touch events, which may confuse the user; use IME_FLAG_NO_FULLSCREEN instead for a better experience. Using this flag is discouraged and it may become deprecated in the future. Its meaning is unclear in some situations and it may not work appropriately on older versions of the platform.

Constant Value: 268435456 (0x10000000)
IME_FLAG_NO_FULLSCREEN
Added in API level 11

public static final int IME_FLAG_NO_FULLSCREEN
Flag of imeOptions: used to request that the IME never go into fullscreen mode. By default, IMEs may go into full screen mode when they think it's appropriate, for example on small screens in landscape orientation where displaying a software keyboard may occlude such a large portion of the screen that the remaining part is too small to meaningfully display the application UI. If this flag is set, compliant IMEs will never go into full screen mode, and always leave some space to display the application UI. Applications need to be aware that the flag is not a guarantee, and some IMEs may ignore it.

Constant Value: 33554432 (0x02000000)
 

Erel

Administrator
Staff member
Licensed User

agraham

Expert
Licensed User
someone added an EditText named edtSource.
It was my EditText called edtSource that it was intended to affect. However you are probably correct that it was doing nothing as I looked into the demo source and found this 😮
B4X:
    ' keep edtSource visible in landscape
    jo = edtSource
    jo.RunMethod("setImeOptions", Array(33554432)) ' IME_FLAG_NO_FULLSCREEN
So the manifest line was probably a hangover from earlier attempts that I should have removed but didn't. I can't remember things like I used to be able to when I was young(er) :(

@alimanam3386 Just remove the line from the manifest - as Erel said it was doing nothing useful.
 
Top