iOS Question Button Event not triggered

iCAB

Well-Known Member
Licensed User
Longtime User
I am having an issue with button click event not being triggered as expected in B4I (works ok with B4A )

1. I have a class that displays a custom numeric keypad popup
2. the keypad is drawn in code, by calling a Sub that resides in another code module (not in the same class)
3. Events are not triggered

I narrowed down the issue to the sample code below

B4X:
    Dim PopupPanel1 As Panel


    PopupPanel1.Initialize("NumericKeypad")
    PopupPanel1.Tag = "NumericKeypad"
    PopupPanel1.Color = Colors.ARGB(200,58,58,58 )
    ParentPanel.AddView(PopupPanel1, 0,0,100%x, 100%y)


    'LayoutSupport.LAY_TESTButton(PopupPanel1)

'This code when called from within the class, the events are triggered no problem
'if this code is placed in another code module and called as in LayoutSupport.LAY_TESTButton(PopupPanel1), no events are triggered 
    Dim btnTestKey As Button

    btnTestKey.InitializeCustom("btnKeypad", Colors.Blue, Colors.Red)
    btnTestKey.Text = "Test"
    btnTestKey.CustomLabel.TextAlignment =  LayoutSupport.LAY_ConvertToB4IJustify(btnTestKey.CustomLabel.ALIGNMENT_CENTER, "Label")
    btnTestKey.CustomLabel.Font = Font.CreateNew(20)
    btnTestKey.Tag = "btnKeypad:1"
    btnTestKey.CustomLabel.Font = Font.DEFAULT_BOLD
    LayoutSupport.SetBackgroundImage(btnTestKey, LayoutNonGUI.LAY_LoadBitMap("btn_green_blank.png", 10%x, 10%y), 0 )               
    LayoutSupport.SetBackgroundImage(btnTestKey, LayoutNonGUI.LAY_LoadBitMap("btn_green_blank.png", 10%x, 10%y), 1 )               
    LayoutSupport.SetBackgroundImage(btnTestKey, LayoutNonGUI.LAY_LoadBitMap("btn_green_blank.png", 10%x, 10%y), 2 )               
    btnTestKey.Enabled = True
    PopupPanel1.AddView( btnTestKey, 30%x, 30%y, 10%x, 10%y)


Please comment
 

iCAB

Well-Known Member
Licensed User
Longtime User
No problem, but unfortunately it is not the same issue.
I already tried the solution provided in the other thread, but it doesn't resolve the button_click event
Thanks again
 
Upvote 0

iCAB

Well-Known Member
Licensed User
Longtime User
I am attaching a small project to duplicate the issue. Here are some notes that could be helpful

1. I added LAY_AddKey, in main. This shows how the button added in main generates a click event
2. I added a code module called LayoutSupport, that has as Lay_AddKey, which almost a copy of the one in main, with the difference that it will accept a panel as a parameter. The other thing that I did, I changed the button tag to reference "Me", passed from the main program (but I wasn't sure if this is what you asked me to do)

Please see attached.
Thanks again
 

Attachments

  • AddViewTest.zip
    2.7 KB · Views: 187
Upvote 0

ilan

Expert
Licensed User
Longtime User
1. you should add views in (or after) page_resize was called.

2. the button click event is fired:

screen1.jpg


3. if you add a view (button,...) from another code module you need to handle that view event in the codemodule you create it:


screen2.jpg
 

Attachments

  • AddViewTest.zip
    3.6 KB · Views: 204
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. you should add views in (or after) page_resize was called.
That's not correct. It is usually a bad idea to add views in the resize event.

if you add a view (button,...) from another code module you need to handle that view event in the codemodule you create it:
That's true.

In B4A code modules cannot handle events so the events are handled in the "parent" module. This is not the case in B4i.
Classes are more powerful and are better suited for custom views.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
That's not correct. It is usually a bad idea to add views in the resize event.

Yes u r right (it would add duplicate views if you would rotate your phone or get a call while u r in your app,...)

I wanted to say set the size+position in resize event.
 
Last edited:
Upvote 0

iCAB

Well-Known Member
Licensed User
Longtime User
In B4A code modules cannot handle events so the events are handled in the "parent" module. This is not the case in B4i.
Classes are more powerful and are better suited for custom views.

Erel, I would appreciate some workaround. You have no idea what that means for me at this stage. The whole code designed based on a single module that draws all the screens. Every single view in the app is created from inside a single common shared module based on B4A. It will be impossible to recreate the code in all the modules ..
 
Upvote 0

iCAB

Well-Known Member
Licensed User
Longtime User
Intercept the event in the static code module and call Main.btnKeypad_Click.
I am not sure that can be achieved easily. The sample code provided is a very simplified version of the actual code.
There is 40+ popups that are displayed from various parts of the code as in.

Dim clsPopup as PopupNumKeypad
clsPopup.Open ...

On top of that, many popups use similar event names (for example: btnBackSpace_Click, could be used in several popups )

Please advise
 
Last edited:
Upvote 0

iCAB

Well-Known Member
Licensed User
Longtime User
Hi Erel,
I would definitely need your help to get this going. Let me clarify for you the structure so you will have a better understanding, and hopefully you can help me find a solution:

1. I am porting a B4A app to B4I
2. As I mentioned earlier, all GUI controls are created in code
3. The typical steps are like this
  • Activity Create: adds a panel
  • Calls Draw_screen: which reads the layout from a .csv file
  • the .csv file is passed to a code module that create the controls by calling another low level function that creates each and every control
4. The above works ok with B4A but as I mentioned there is an issue with B4I events

5. Steps that I have taken so far:
  • Converted the higher level LayoutSupport module that holds Draw_Screen and other higher level functions to a class
  • Created a separate class for CreateView
  • Layout Support declares an instant of CreateView in its Class_Globals
  • The instance is used to create all controls on the popup/activity
  • Inside CreateView I am using internal events and keeping a log that matches tags to events

Now I am getting events to fire inside CreateView Class (so far we are only talking B4A, but that is the first step for me to be able to test the structure)

All Button events are triggering the class event for button click, which I am hoping to dispatch from here to initiating activity or class

B4X:
Private Sub Button_Click
    Dim btn As Button = Sender
    Dim EventName As String = GetEvent( LayoutNonGUI.LAY_BUTTON, btn.Tag )

    If EventName <> "" Then
        EventName = EventName & "_Click"
        CallSub(ClassReferenceObject,  EventName )
    End If

End Sub

in the above we have the "Sender", which is needed for the actual events inside the calling activities.

1. How do I pass the sender without changing the signature for the actual receiving events (for example btn_Click doesn't have any arguments )?

2. Do you think this is the proper of doing it?


I have attached a modified version of the sample project so it will give you a better idea.
Please run the project and click the buttons and see the message in the log

Please advise
 

Attachments

  • AddView2.zip
    3.8 KB · Views: 173
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The standard way to do it is to pass the callback object and the event name when you initialize the class instance:

B4X:
Sub Class_Globals
   Private EventName As String 
   Private CallBack As Object 
End Sub

Public Sub Initialize (vCallback As Object, vEventName As String)
   EventName = vEventName
   CallBack = vCallback
End Sub

Private Sub Button_Click
 CallSub(CallBack, EventName & "_btnClick")
End Sub
 
Upvote 0

iCAB

Well-Known Member
Licensed User
Longtime User
To get reference to the original sender this is what I have done, but I am wondering if there is a cleaner way.

B4X:
Private Sub Button_Click
   'Save global copy of sender in here
CallSub(CallBack, EventName & "_btnClick")
End Sub

in the original btnClick event, I am using the global copy

My other related questions, is this:
What if the Sub doesn't exist?, try catch is not trapping the error
 
Last edited:
Upvote 0

iCAB

Well-Known Member
Licensed User
Longtime User
Nothing will happen if the sub doesn't exist.
Please note that I am trying to have my implementation work for B4I and B4A equally.
I am getting the error with B4A ( I didn't want to create a new thread for this question, as this may come in hand to others in the same place)
 
Upvote 0
Top