Android Question [B4X] [Solved] 2 instances of B4XDialog in the same activity: show the 2nd above the 1st

Toky Olivier

Active Member
Licensed User
Hello all,
Is it possible to declare and use 2 instances of B4XDialog in the same activity please?
I tried it: I open a custom dialog and in that, I would like to open another dialog. The issue is, the first dialog is closed when the second is opened.
I want that the first remain active while the second dialog is shown.
Thank you.
 

Toky Olivier

Active Member
Licensed User
Thank you but Is there any method to not let the first dialog to not close?
For example, in the first dialog (custom dialog), I have a CustomListView where Items can be deleted separately. When users click sur Delete on an item, I want to ask confirmation with an another B4XDialog. After confirmation, I should come back to the first dialog with the item deleted.
 

Erel

Administrator
Staff member
Licensed User
hank you but Is there any method to not let the first dialog to not close?
Not without modifying B4XDialog source code.

When users click sur Delete on an item, I want to ask confirmation with an another B4XDialog. After confirmation, I should come back to the first dialog with the item deleted.
This is exactly the flow that happens in B4XPreferencesDialog. It is not trivial but you can see how it is implemented there.
 

Toky Olivier

Active Member
Licensed User
Thank you,

This is exactly the flow that happens in B4XPreferencesDialog. It is not trivial but you can see how it is implemented there.
I did something like this now but it's not too good to see... It's better to have another option.

Another option is to use Msgbox2Async with the second dialog.
I've already think about it but that dialog is not customizable like B4XDialog...

I'll look at the source and see what I can do. Thank you.
 

Toky Olivier

Active Member
Licensed User
Good evening all,
This is my attempt to solve the problem but I'm facing to another problem.
The second dialog is shown and can be closed (and return value) but the first, after the second is closed, cannot be closed in his turn.
It seems that the CallSubDelayed2 is not called after the top most dialog is closed.
B4X:
Public Sub Close (Result As Int) As Boolean
    If getVisible Then
        Log("Attempt to close")
        CallSubDelayed2(Me, "CloseMessage", Result)
        Return True
    End If
    Return False
End Sub
Attached the sample project with the modified B4XDialog class.

Edit: The CallSubDelayed2 sub is called but may be the "Wait For" doesn't handle it.
 

Attachments

stevel05

Expert
Licensed User
The B4xDialog2 code works, you need to have 2 separate instances of dialog2 in Main:

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

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.
    Dim xui As XUI
    Dim dlg As B4XDialog2
    Dim dlg2 As B4XDialog2
    Dim Base As B4XView
    Private Button1 As Button
    Private btnInsideDlg1 As Button
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")
    Base = Activity
    dlg.Initialize(Base)
    dlg2.Initialize(Base)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
    If KeyCode = KeyCodes.KEYCODE_BACK And dlg.Close(xui.DialogResponse_Cancel) Then Return True
    Return False
End Sub


Sub Button1_Click
    Dim pnl As B4XView = xui.CreatePanel("")
    pnl.SetLayoutAnimated(0,0,0,350dip,250dip)
    pnl.LoadLayout("dlg1")
    dlg.Title = "Dialog 1"
    Dim rs As ResumableSub = dlg.ShowCustom(pnl,"Yes","No","")
    Wait For (rs) Complete(Result As Int)
    Log(Result)
End Sub

Sub btnInsideDlg1_Click
    Dim pnl As B4XView = xui.CreatePanel("")
    pnl.SetLayoutAnimated(0,0,0,150dip,150dip)
    pnl.LoadLayout("dlg2")
    dlg2.Title = "Dialog 2"
    dlg2.ShowOnTop = True 'This make the new dialog to show on top of already shown dialog
    Dim rs As ResumableSub = dlg2.ShowCustom(pnl,"Eny","Tsia","")
    Wait For (rs) Complete(Result As Int)
    Log(Result)
End Sub
 
Last edited:

Toky Olivier

Active Member
Licensed User
Hello all,
Thank you but As I put in the fist post, and replied by @Erel, I want to put the 2nd dialog above the first. Now, with B4XDialog, you cannot do that unless you modify the source he confirmed. That's why I modified it to B4XDialog2 but there are some adjustment I missed may be. The first dialog cannot be closed as you can see if you run the test project I sent.
 

rraswisak

Active Member
Licensed User
i suggest you to remove dlg variable on Globals Sub and dlg.Initialize(Base) from activity_create,
Declare dlg variable on each button click sub and don't forget to initialize the variable
 

Toky Olivier

Active Member
Licensed User
i suggest you to remove dlg variable on Globals Sub and dlg.Initialize(Base) from activity_create,
Declare dlg variable on each button click sub and don't forget to initialize the variable
I analyzed B4XDialog source, it's the conception of B4XDialog that make it to show only ONE dialog in the same time whatever we declare in 2 or more variables. Before showing one dialog, it searches previously shown dialog and deletes it from its parent. So, only one dialog will be shown. That's why I modified it with my version B4XDialog2. As I said, the problem is in that code:
B4X:
Public Sub Close (Result As Int) As Boolean
    If getVisible Then
        Log("Attempt to close")
        CallSubDelayed2(Me, "CloseMessage", Result)
        Return True
    End If
    Return False
End Sub
The Wait For instruction below does'nt handle the "CloseMessage" for the 2nd dialog.

B4X:
...
For Each v As B4XView In tBg.GetAllViewsRecursive
        v.Enabled = True
    Next
    Log(tBg.Tag)
    Wait For CloseMessage (Result As Int)
    Log(tBg.Tag)
    For Each v As B4XView In tBg.GetAllViewsRecursive
        v.Enabled = False
    Next
...
 

rraswisak

Active Member
Licensed User
The Wait For instruction below does'nt handle the "CloseMessage" for the 2nd dialog
Its because in your project dlg is declared in GlobalbSub, i run your project and had modify as my suggestion above, both dialog can be shown and close perfectly
 

Toky Olivier

Active Member
Licensed User
ts because in your project dlg is declared in GlobalbSub
You should, if not, you cannot handle the "Back key" in the KeyPress event and close the Dialog.

And as I said, the second dialog is shown after the first dialog not Above. See attached test project.

What I want to have is this:
B4XDialog2.png
 

Attachments

Toky Olivier

Active Member
Licensed User
The B4xDialog2 code works, you need to have 2 separate instances of dialog2 in Main
I misunderstood your response before, sorry. It works, thank you.
But... Now, the problem is to find a way to close topmost dialog first when pressing Back key. With only two dialogs, it's easy but if there are many, it becames difficult.
With two dialogs, I do it like this:
B4X:
Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
    If KeyCode = KeyCodes.KEYCODE_BACK Then
        If dlg2_shown Then
            If dlg2.Close(xui.DialogResponse_Cancel) Then Return True
        Else
            If dlg1_shown And dlg.Close(xui.DialogResponse_Cancel) Then Return True
        End If     
    End If
    Return False
End Sub
Attached the new project with the B4XDialog2 class.
 

Attachments

Toky Olivier

Active Member
Licensed User
Finally I found a way to do it easily with the fresh source of B4XDialog. I created a simple class B4XDialog2Manager to manage each instance of B4XDialog2.
Now on the KeyPress event, it's only:
B4X:
Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
    If KeyCode = KeyCodes.KEYCODE_BACK And dlgm.CloseTopMostDialog(xui.DialogResponse_Cancel) Then Return True
    Return False
End Sub
And to create a new dialog, I do like this:
B4X:
Sub Button1_Click
    Dim pnl As B4XView = xui.CreatePanel("")
    pnl.SetLayoutAnimated(0,0,0,350dip,250dip)
    pnl.LoadLayout("dlg1")
    Dim dlg As B4XDialog2 = dlgm.CreateDialog
    dlg.Title = "Dialog 1"
    dlg.BlurBackground = True
    Dim rs As ResumableSub = dlg.ShowCustom(pnl,"Yes","No","")
    Wait For (rs) Complete(Result As Int)
    Log(Result)
End Sub
Attached the sample project file with the two classes: B4XDialog2 and B4XDialog2Manager if someone is interested.

B4XDialog2.png
 

Attachments

stevel05

Expert
Licensed User
That would have been my suggestion :) Glad it's working
 
Top