erel's comment:
got my attention.
not only must the event be trapped by the view with the focus, but - apparently - it goes a step further: to the keyboard itself.
in order to get the back key press into the hands of the activity (for whatever it is you might want to do in that case), you need to know if the keyboard is visible and if the edittext has the focus. if one or both are true, the activity doesn't see the key press.
so what i did was add a listener to the keyboard's visibility. when you tap the back key, the keyboard disappears (as usual), but what happens next is up to you. you can allow normal flow or abnormal flow, and you can toggle the flow on the fly.
the normal flow (in my opinion) would be: tap back key to remove keyboard (as usual) and set the activity to receive the next back key tap. this does not occur now because the edittext still has the focus even though the keyboard is gone. if you wish, you can reset the focus when the app is notified the keyboard is gone.
abnormal flow (in my opinion) would be: tap back key while keyboard is up but have activity receive the key press immediately (which, i think, is what you were looking for). here, you have to decide whether to consume the event or not. but this has nothing to do with my code. to consume or not to consume is always something you have to deal with.
the code is simple enough. you need 2 javaobjects, 1 javaobject call to unset the focus and 1 inline java routine for the listener. you determine which "flow" to use by passing a boolean to the listener. everything is in this post.
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Private xui As XUI
End Sub
Sub Globals
'These global variables will be redeclared each time the activity is created.
Dim jo, edittextjo As JavaObject
Dim edittext1 As EditText
Dim normalflow As Boolean
End Sub
Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("Layout")
jo.InitializeContext
edittextjo = edittext1
normalflow = True
jo.RunMethod("setListener",Array( edittext1,normalflow ))
End Sub
Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub edittext1_FocusChanged (HasFocus As Boolean)
Log("has focus: " & HasFocus)
End Sub
Sub kbdtoggle( height As Int )
If height = 0 Then
Log("keyboard gone, but edittext still has focus. it keeps the focus until you clear it below.")
' run this to clear the focus
' edittextjo.RunMethod("clearFocus",Null)
End If
End Sub
Sub activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
If KeyCode = KeyCodes.KEYCODE_BACK Then
If edittextjo.RunMethod("hasFocus",Null) Then
Log("edittext has focus. activity blocked. you'll keep coming back here until you clear the focus below.")
' if you run this, activity will receive the next back key press
' edittextjo.RunMethod("clearFocus",Null)
Return True ' up to you to consume or not
Else
Log("activity captures back key. consuming event, but you could fall through if you wanted")
Return True ' up to you to consume or not
End If
End If
End Sub
#if Java
import android.view.WindowInsets;
import android.view.View;
import android.view.WindowInsets.Type;
import android.view.KeyEvent;
import android.view.View.OnApplyWindowInsetsListener;
public void setListener( View view, boolean normalFlow ) {
view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
boolean imeVisible = insets.isVisible(WindowInsets.Type.ime());
int imeHeight = insets.getInsets(WindowInsets.Type.ime()).bottom;
BA.Log("height: " + imeHeight);
if ( (imeHeight == 0) && (normalFlow == false) ) {
view.clearFocus();
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
}
processBA.raiseEvent(this, "kbdtoggle",new Object[] {imeHeight});
return null;
}
});
}
#end if
'----------------------------------------------------------------------------------------------------
now the deal breaker: we are supposed to use the jetpack/androidx.core
ViewCompat artifact for the listener. although i have androidx.core package
in the sdk, i have never been able to compile anything that imports any of its
members. this, even though erel has said that it should work with inline java.
whatever. i believe the purpose of the many so-called "Compat" packages
is to maintain backward compatibility with older android devices. i don't
have any, so although i couldn't use ViewCompat, i just used good old
android.view.View class for the listener. i mention this only as a rationale as
to why i used View instead of ViewCompat in case somebody should notice.
whether this or the actual code might knock you off Play, i can't say.
i thought the exercise itself was of interest.