Introduction
Since we discovered b4a I looked for a flexible and developer friendly dialog library with an extensive and versatile object model. Unfortunately I could not find anything that could satisfy our development requirements so I decided to write one.
This tutorial is available in the latest XtraViews package and as standalone APK
Part 1 Creating a custom login dialog
DialogViews are based on layouts that are build with the b4a integrated dialog designer. First of all, design the layout like you do with any other activity layout. Start with dropping a panel and then drop all needed controls inside that panel. In our case, 2 textedit controls. Set the appropriate anchors save the layout into the "dialog1" file and move on to the code.
Let's instantiate our DialogView in our Sub Globals:
In our button click handler, load the layout in the dialog and show it.
Note that dialog1 is the name of the layout file. The engine will open the layout, extract the first panel that it will find and will generate our dialog with the views inside. The ShowYesNo method will show the dialog with a system title and 2 buttons.
Part 2 Accessing views in the dialog
Now that we have our barebone dialog, we can proceed with accessing its views. Lets add a label in our layout and change it's text and color in code. In order to do this we have to break our single function call into several parts.
First, create a DialogViewLayout object using our global DialogView instance and load our layout.
Then, get a handle of the label we want to access
Set the label properties
Finally, call our ShowYesNo method
One powerful feature of the DialogView engine are the events that will be raised before the dialog is shown and before the dialog is dismissed.
Part 3 Advanced event handling
Now that we know how to access views in our layout, let's go a step further and do something more complicated.
Lets add a Button that we will use to clear the fields. When ever the text changes, our code will enable or disable the clear button accordingly.
Now, let's write the code that will enable/disable the clear button
Generate the TextChanged event from the layout designer for both textedits and call the previous function.
Generate the Click handler for the BtnClear button from the layout designer
In our Dialog3_Dismiss event we cancel the dialog dismiss if the user has clicked the "proceed" button and the textedits are not filled in.
Finally, we show the dialog and with the Msgbox function of the DialogView the user input.
Part 4 Listview and layout per orientation
Now, lets make it a little bit more complex. Let's create 2 different layouts containing some buttons and a listview. One for portrait and one for landscape.
Another powerful feature of the DialogView engine is that whenever the user clicks on a button with a numeric id in its tag, the DialogView will dismiss itself and will return the tag of that button as a result. Following that methodology, let's set Button1 tag to 1 and Button2 tag to 2.
Create the function that we will use to add some items to the listview
Then, create the Click handler of the BtnBeepAndAddItems button in the layout designer
Create the ItemClick handler of the ListView1 in the layout designer
Load the multiple layouts by using the LoadLayoutMultiple method
Get a reference of the ListView1 from the layout, set the textcolor and add 10 items to it
Finally, show the dialog without the system title and buttons
Part 5 A reusable custom dialog
After having gone through the previous steps, it is very easy even to create a reusable custom dialog.
Set the tag of the label that your want to use as a title to "title" and the tag of the label you want to use as content to "content" and call the following function:
Part 6 Customizing the system and any other dialog
The DialogView.Options property has a wide range of configuration options that you can set in order to totally alter the look and feel of everything in a dialog. For example:
Configure the dialog title
Configure the message content
Configure the dialog buttons
Or set the style in one line
Part 7 Applying animations and gravity
Adding animation to any type of dialog is very simple.
To set the gravity of the dialog:
Part 8 Customizing dialog dimensions
If you want to have specific dialog dimensions based on a display ratio or fixed values, just use the DialogView.Options.Dimensions property.
If you use the DialogView.Options.Dimensions.MODE_ANCHORS mode, the engine will respect any anchors that are set and will resize the views accordingly. Using the DialogView.Options.Dimensions.MODE_STRETCH mode, will stretch and reposition all views to fit the new dimensions nicely. Using the DialogView.Options.Dimensions.MODE_STRETCH_TEXT mode, is the same like MODE_STRETCH but it will try to adjust the textsize of affected buttons and textviews.
--
That was all for now folks!
Tip: All dialog fields (title, message, button captions) accept HTML as an input that will be properly displayed.
There are a lot more things hidden. Play with it and you will discover them!
Enjoy!
Since we discovered b4a I looked for a flexible and developer friendly dialog library with an extensive and versatile object model. Unfortunately I could not find anything that could satisfy our development requirements so I decided to write one.
This tutorial is available in the latest XtraViews package and as standalone APK
Part 1 Creating a custom login dialog
DialogViews are based on layouts that are build with the b4a integrated dialog designer. First of all, design the layout like you do with any other activity layout. Start with dropping a panel and then drop all needed controls inside that panel. In our case, 2 textedit controls. Set the appropriate anchors save the layout into the "dialog1" file and move on to the code.
Let's instantiate our DialogView in our Sub Globals:
B4X:
Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.
Dim Dialog As DialogView
End Sub
B4X:
Dialog.LoadLayout("dialog1").ShowYesNo("Login", "proceed", "later")
Part 2 Accessing views in the dialog
Now that we have our barebone dialog, we can proceed with accessing its views. Lets add a label in our layout and change it's text and color in code. In order to do this we have to break our single function call into several parts.
First, create a DialogViewLayout object using our global DialogView instance and load our layout.
B4X:
Dim DialogLayout As DialogViewLayout
DialogLayout = Dialog.LoadLayout("dialog2")
B4X:
Dim Label1 As Label = DialogLayout.Views.Get("label1")
B4X:
Label1.Text = "Please login below:"
Label1.TextColor = Colors.Red
B4X:
Dim Result As Int = DialogLayout.ShowYesNo("Login", "proceed", "later")
Main.Toast.Show("Result = " & Result)
One powerful feature of the DialogView engine are the events that will be raised before the dialog is shown and before the dialog is dismissed.
B4X:
Sub Dialog2_Show
'This event will be raised just before the dialog is closed passing the DialogResult
Main.Toast.Show(Dialog.Name & " is shown")
End Sub
Sub Dialog2_Dismiss (DialogResult As Int) As Boolean
'This event will be raised just before the dialog is closed passing the DialogResult
'Return true to dismiss or false to cancel
Return True
End Sub
Part 3 Advanced event handling
Now that we know how to access views in our layout, let's go a step further and do something more complicated.
Lets add a Button that we will use to clear the fields. When ever the text changes, our code will enable or disable the clear button accordingly.
Now, let's write the code that will enable/disable the clear button
B4X:
Sub SetBtnClearState
'Get the EdUserName and EdPassword from the layout
Dim EdUserName As Label = Dialog.Views.Get("EdUserName")
Dim EdPassword As Label = Dialog.Views.Get("EdPassword")
'Get the BtnClear from the layout
Dim BtnClear As Button = Dialog.Views.Get("BtnClear")
'Enable or disable the BtnClear according to user input
BtnClear.Enabled = EdUserName.Text <> "" OR EdPassword.Text <> ""
End Sub
B4X:
Sub EdElement_TextChanged (Old As String, New As String)
'Use CallSubDelayed in order to avoid deadlocks
CallSubDelayed(Me, "SetBtnClearState")
End Sub
B4X:
Sub BtnClear_Click
'Get the EdUsername from the layout AND clear it
Dim EdUserName As Label = Dialog.Views.Get("EdUserName")
EdUserName.Text = ""
'Get the EdPassword from the layout and clear it
Dim EdPassword As Label = Dialog.Views.Get("EdPassword")
EdPassword.Text = ""
End Sub
B4X:
Sub Dialog3_Dismiss (DialogResult As Int) As Boolean
'This event will be raised just before the dialog is closed passing the DialogResult
'Return true to dismiss or false to cancel
Dim AllowDismiss As Boolean
If DialogResult = DialogResponse.POSITIVE Then
'Get the edit views contents
Dim EdUserName As Label = Dialog.Views.Get("EdUserName")
Dim EdPassword As Label = Dialog.Views.Get"EdPassword")
'if any of them is empty return false
AllowDismiss = EdUserName.Text <> "" AND EdPassword.Text <> ""
Else
AllowDismiss = True
End If
If Not(AllowDismiss) Then Main.Toast.Show("all fields are required!")
Return AllowDismiss
End Sub
B4X:
Dim Result As Int = DialogLayout.ShowYesNo("Login", "proceed", "later")
If Result = DialogResponse.POSITIVE Then
Dim EdUserName As Label = Dialog.Views.Get("EdUserName")
Dim EdPassword As Label = Dialog.Views.Get("EdPassword")
Dialog.Msgbox("DialogView", "<b>Username:</b> " & EdUserName.Text & "<br/><br/>" & "<b>Password:</b> " & EdPassword.Text, "done", "", "", LoadBitmap(File.DirAssets, "icon1.png"))
End If
Part 4 Listview and layout per orientation
Now, lets make it a little bit more complex. Let's create 2 different layouts containing some buttons and a listview. One for portrait and one for landscape.
Another powerful feature of the DialogView engine is that whenever the user clicks on a button with a numeric id in its tag, the DialogView will dismiss itself and will return the tag of that button as a result. Following that methodology, let's set Button1 tag to 1 and Button2 tag to 2.
Create the function that we will use to add some items to the listview
B4X:
Sub AddItemsToTheListView(ListView As ListView)
Dim Count As Int = ListView.Size
For i=1 To 10
ListView.AddSingleLine("item #" & (Count + i))
Next
ListView.SetSelection(ListView.Size)
End Sub
B4X:
Sub BtnBeepAndAddItems_Click
Dim Beeper As Beeper : Beeper.Initialize(300, 500) : Beeper.Beep
Dim ListView As ListView = Dialog.Views.Get("ListView1")
AddItemsToTheListView(Dialog.Views.Get("ListView1"))
Main.Toast.Show("10 items added to the listview (total: " & ListView.Size & ")")
End Sub
B4X:
Sub ListView1_ItemClick (Position As Int, Value As Object)
Main.Toast.Show("listview (pos #" & Position & ") = " & Value)
End Sub
B4X:
Dim DialogLayout As DialogViewLayout
DialogLayout = Dialog.LoadLayoutMultiple("dialog4_portrait", "dialog4_landscape", "dialog4")
B4X:
Dim ListView1 As ListView = DialogLayout.Views.Get("ListView1")
ListView1.SingleLineLayout.Label.TextColor = Colors.Black
AddItemsToTheListView(ListView1)
B4X:
Dim Result = DialogLayout.ShowDefault
Part 5 A reusable custom dialog
After having gone through the previous steps, it is very easy even to create a reusable custom dialog.
Set the tag of the label that your want to use as a title to "title" and the tag of the label you want to use as content to "content" and call the following function:
B4X:
Dim Result As Int = Dialog.LoadLayout("dialog5").ShowDefault2("This is a title", "This is a custom content")
Part 6 Customizing the system and any other dialog
The DialogView.Options property has a wide range of configuration options that you can set in order to totally alter the look and feel of everything in a dialog. For example:
Configure the dialog title
B4X:
Dim TitleBackground As ColorDrawable : TitleBackground.Initialize(Colors.Gray, 0)
Dialog.Options.Title.Set(Typeface.CreateNew(Typeface.SANS_SERIF, Typeface.STYLE_BOLD_ITALIC), Colors.Blue, 25, Gravity.CENTER, TitleBackground, Colors.Red)
B4X:
Dim MessageBackground As ColorDrawable : MessageBackground.Initialize(Colors.Magenta, 0)
Dialog.Options.Message.Set(Typeface.CreateNew(Typeface.SANS_SERIF, Typeface.STYLE_BOLD_ITALIC), Colors.Blue, 25, Gravity.CENTER, MessageBackground)
B4X:
Dim ButtonBackground As StateListDrawable : ButtonBackground.Initialize
Dim ButtonBackgroundNormal As ColorDrawable : ButtonBackgroundNormal.Initialize(Colors.Yellow, 0)
Dim ButtonBackgroundPressed As ColorDrawable : ButtonBackgroundPressed.Initialize(Colors.Cyan, 0)
ButtonBackground.AddState(ButtonBackground.State_Pressed, ButtonBackgroundPressed)
ButtonBackground.AddCatchAllState(ButtonBackgroundNormal)
Dim ButtonStyle1, ButtonStyle2, ButtonStyle3 As DialogViewButtonStyle
ButtonStyle1.Set(Typeface.CreateNew(Typeface.SANS_SERIF, Typeface.STYLE_NORMAL), Colors.Blue, 14, Gravity.LEFT + Gravity.BOTTOM, ButtonBackground)
ButtonStyle2.Set(Typeface.CreateNew(Typeface.SANS_SERIF, Typeface.STYLE_BOLD), Colors.Red, 14, Gravity.LEFT + Gravity.Top, ButtonBackground)
ButtonStyle3.Set(Typeface.CreateNew(Typeface.SANS_SERIF, Typeface.STYLE_BOLD_ITALIC), Colors.Black, 24, Gravity.CENTER, ButtonBackground)
'Dialog.Options.Buttons.Default.Style = ButtonStyle1 <= apply the style to all buttons
Dialog.Options.Buttons.Positive.Style = ButtonStyle1
Dialog.Options.Buttons.Neutral.Style = ButtonStyle2
Dialog.Options.Buttons.Negative.Style = ButtonStyle3
B4X:
Dialog.Options.Buttons.Default.Style.Set(Typeface.CreateNew(Typeface.SANS_SERIF, Typeface.STYLE_NORMAL), Colors.Blue, 14, Gravity.LEFT + Gravity.BOTTOM, ButtonBackground)
Part 7 Applying animations and gravity
Adding animation to any type of dialog is very simple.
- Copy the AssetsXtra folder from the tutorial sample root folder to your project's root folder
- Add this directive to your project attributes:
B4X:
#AdditionalRes: ..\AssetsXtra
- Finally set the animation:
B4X:
Dialog.Options.Animation = "<animation_name>"
- zoom
- slide_from_top, slide_from_top_and_back
- slide_from_bottom, slide_from_bottom_and_back,
- slide_from_left,slide_from_left_and_back,
- slide_from_right,slide_from_right_and_back
To set the gravity of the dialog:
B4X:
Dialog.Options.Gravity = Gravity.RIGHT + Gravity.BOTTOM
Part 8 Customizing dialog dimensions
If you want to have specific dialog dimensions based on a display ratio or fixed values, just use the DialogView.Options.Dimensions property.
If you use the DialogView.Options.Dimensions.MODE_ANCHORS mode, the engine will respect any anchors that are set and will resize the views accordingly. Using the DialogView.Options.Dimensions.MODE_STRETCH mode, will stretch and reposition all views to fit the new dimensions nicely. Using the DialogView.Options.Dimensions.MODE_STRETCH_TEXT mode, is the same like MODE_STRETCH but it will try to adjust the textsize of affected buttons and textviews.
B4X:
Dialog.Options.Dimensions.Set(100%x, 100%y, Dialog.Options.Dimensions.MODE_ANCHORS)
--
That was all for now folks!
Tip: All dialog fields (title, message, button captions) accept HTML as an input that will be properly displayed.
There are a lot more things hidden. Play with it and you will discover them!
Enjoy!
Last edited: