Android Question Event to trap BackKey in a class two times called

welu1805

Active Member
Licensed User
Longtime User
Hi all.

I wrote a little class for an input dialog.

In the class clsDialog I want catch the BackKey. It should not close the whole application, only the actual class instance.

If only the first dialog is started it works like expected: the dialog is closed and the main activity not.

If from the first dialog the second dialog is started with the button "Edit city", the BackKey will close both dialogs and not only the city dialog. In the eventhandler

Sub On_KeyPress(ViewTag As Object, KeyCode As Int, KeyEvent As Object) As Boolean

the return value is "True" so the BackKey event should be consumed!

Why this eventhandler is called 2 times??? See Log("On_KeyPress")

B4X:
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
 
   ' in layout Main
   Private btnDialog As Button
   Private pnlMain As Panel
   
   ' in layout names
   Private btnCity As Button
   Private edtName1 As EditText
   Private edtName2 As EditText
   Private lblName1 As Label
   Private lblName2 As Label
   Private pnlNames As Panel
   
   ' in layout city
   Private edtCity As EditText
   Private edtStreet As EditText
   Private lblCity As Label
   Private lblStreet As Label
   Private pnlAdress As Panel
   
   ' 2 instances of class dialog
   Private dlgNames As clsDialog
   Private dlgAdress As clsDialog
End Sub

Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   Activity.LoadLayout("Main")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnDialog_Click
   Dim pnlDialog1 As Panel
   
   pnlDialog1.Initialize("")
   pnlDialog1.LoadLayout("names")  ' includes pnlNames
   
   dlgNames.Initialize(Activity, pnlNames, edtName1)
   dlgNames.Show
End Sub

Sub btnCity_Click
   Dim pnlDialog2 As Panel
   
   pnlDialog2.Initialize("")
   pnlDialog2.LoadLayout("city")  ' includes pnlAdress
   
   dlgAdress.Initialize(Activity, pnlAdress, edtCity)
   dlgAdress.Show
End Sub

'--------------------------------------------------
' this is the class dialog: clsDialog
'--------------------------------------------------
Sub Class_Globals
   Private aAct As Activity
   Private aPnlInput As Panel
   Private aFirstEditText As EditText
   Private pnlScreen As Panel
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(act As Activity, pnlInput As Panel, firstEditText As EditText)
   aAct = act
   aPnlInput = pnlInput
   aFirstEditText = firstEditText
End Sub

Public Sub Show
   pnlScreen.Initialize("pnlScreen")
   aAct.AddView(pnlScreen, 0, 0, aAct.Width, aAct.Height)
   pnlScreen.Color = Colors.ARGB(150, 0, 0, 0)
   pnlScreen.BringToFront
   
   aPnlInput.RemoveView
   pnlScreen.AddView(aPnlInput, _
    (aAct.Width - aPnlInput.Width)/2, _
                    (aAct.Height - aPnlInput.Height)/2, _
                    aPnlInput.Width, aPnlInput.Height)
                   
   aFirstEditText.RequestFocus
   
   ' for all EditText fields set the eventhandler for KeyPress
   For Each v As View In aPnlInput.GetAllViewsRecursive
     If v Is EditText Then
       SetReflector(v)
     End If
   Next
End Sub

Public Sub SetReflector(v As View)
   Dim r As Reflector
   r.Target = v
   r.SetOnKeyListener("On_KeyPress")
   r.RunMethod2("setFocusable", "True", "java.lang.boolean")
   r.RunMethod2("setFocusableInTouchMode", "True", "java.lang.boolean")
End Sub

Private Sub Hide
   pnlScreen.RemoveView
End Sub

Private Sub pnlScreen_Click
   ' Do Nothing: Prevent panel from click
End Sub

Private Sub On_KeyPress(ViewTag As Object, KeyCode As Int, KeyEvent As Object) As Boolean
   If KeyCode = KeyCodes.KEYCODE_BACK Then
     Log("On_KeyPress")
    Hide
    Return True
   Else
     Return False
   End If
End Sub

Has anyone an idea?

Thanks Lutz
 

Attachments

  • TestDialog.zip
    10.8 KB · Views: 274

Star-Dust

Expert
Licensed User
Longtime User
It is not possible from the class but only from the activity.
See this link where @Filippo puts the same question for a Dialog Class and see answered: https://www.b4x.com/android/forum/threads/fgcustomdialog-modal-dialog.79971/#post-507004

@Erel suggests a little trick to intercept BackKey from Activity and then handle it from class

@Filippo in the same thread as he opens a new Activity within the class to handle BackKey, but this obscures Calling Activity ... this too could be a solution for you. Create a Activity within the class
 
Upvote 0

welu1805

Active Member
Licensed User
Longtime User
It is not possible from the class but only from the activity

WHAT is not possible from the class?

The event handler is called in the class.

B4X:
Sub On_KeyPress(ViewTag As Object, KeyCode As Int, KeyEvent As Object) As Boolean

(This is the last block in the clsDialog.)

The problem is: if from the first instance of clsDialog another instance is created then the BackKey event raises for 2 times (in the second instance) and closes both instances.
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
This wrote EREL, now try
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
The event is fired not only on ACTION_DOWN, but also when it is pressed more that a certain time (repeat) and when you release it. So it is fired multiple times.You are only looking for the first event
Try this
B4X:
Private Sub On_KeyPress(ViewTag As Object, KeyCode As Int, KeyEvent As Object) As Boolean
   If KeyCode = KeyCodes.KEYCODE_BACK Then
  
     Dim j As JavaObject = KeyEvent
     Dim eventCode As Int = j.RunMethod("getAction",Null)
     Log("EventCode is:"&eventCode)
     if (eventCode = 0) Then Hide     ' 0=ACTION_DOWN, 1=ACTION_UP, 2=ACTION_MULTIPLE
     Return True

   Else

     Return False

   End If
End Sub
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
You are right, but also Erel,
You talk about the EditText object, Erel in general about the panels and buttons
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
However today I learned a very useful thing thanks to you ;)
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Is 30dip;) for 30dip
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
I posted this solution to the thread where erel said it was not possible ... :p:p:p:p
 
Upvote 0

Star-Dust

Expert
Licensed User
Longtime User
Having done the eprove, I observed that it moves the KeyPress event to the On_KeyPress sub, but at the end of the panel it should return control to Activity_KeyPress.

Is there a way to restore event control to activity?
 
Upvote 0
Top