Share My Creation Interactive expandable multi B4XPages Drawer menu (tested in B4J and B4A)

In the five years that I have been using my single B4XPage expandable Drawer menu in B4J and B4A, both the IDEs and the B4X components have evolved. The time was ripe to create a new version called m3Menu. Below the result and an overview of the possibilities:

1740403223221.png


The starting point was that the program should be able to easily adjust the menu groups, the associated menu items and icons. I also added the programming option to block an entire menu group or one or more items of a menu group for those who need more than a simple drop-down menu.

The pragmatic choice for the 719 material design icons is a compromise to be able to give the icons the same color as the menu grep title and menu item titles. I was a bit too lazy to pick out a unique icons from the 719 material design icons for the POC for each menu option. It is best to use Erel's [B4X] MaterialIcons Web Font Chooser program to choose the icon you want to use.
The colors used can be used as HTML hexadecimal color code, as well as standard XUI color palette code.

I have paid a lot of attention to making the reusability and adaptability to personal wishes as great and easy as possible for both the novice and the advanced forum members. The easiest way is to add your B4XPage(s) to the Proof Of Concept(POC) and add the code below to your B4XPage(s). The easiest way is to do the testing in B4J according to the following scheme:

1740405781128.png


By using B4X components as much as possible, the #IF B4J or #IF B4A constructions are avoided and the developed B4J form(s) can be shared between the two development environments via a copy-paste action.

To add an existing m3Menu to an (existing) B4XPage the following steps are required:
Step 1: Global variables in each B4XPage:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    
'    --- M3Menu Variables
    Private drManager As DrawerManager
    Private clvMenu As CustomListView
    Private lblMenuInfo As B4XView

End Sub

Step 2: Add Drawer initialization:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
        
'    --- Initialize B4XMenu
    drManager.Initialize(Me, "Drawer", Root)
'    --- Load the required page layout here
    drManager.Drawer.CenterPanel.LoadLayout("frmPage1")
    drManager.Drawer.LeftPanel.LoadLayout("frmLeftMenu")
    drManager.Drawer.LeftPanel.Color = drManager.tms.MenuColor
    clvMenu = drManager.createMenu(clvMenu)
    lblMenuInfo.Text = drManager.tms.MenuInfoText
    lblMenuInfo.TextColor =drManager.tms.menuTextColor
        
End Sub

Step 3: Link the Drawer routines add to the B4XPages:
' --- Check Draw Menu
#IF B4J
    Public Sub imgHamburger_MouseClicked (EventData As MouseEvent)
        drManager.imgHamburger_MouseClicked(EventData)
    End Sub

    Private Sub lblMenuInfo_MouseClicked (EventData As MouseEvent)
    drManager.LogPrt($"Logo clicked!"$)
    End Sub

#End If

Private Sub B4XPage_Appear
    drManager.B4XPageAppear(clvMenu)
End Sub

Private Sub B4XPage_CloseRequest As ResumableSub
    Return drManager.B4XPageCloseRequest
End Sub

Private Sub B4XPage_Disappear
    drManager.B4XPageDisappear
End Sub

' --- Needed for DrawerMenu
Private Sub B4XPage_Resize (Width As Int, Height As Int)
    drManager.Drawer.Resize(Width, Height)
End Sub

'Check Draw Menu
Private Sub clvMenu_ItemClick(Index As Int, Val As Object)
    drManager.CLVMenu_ItemClick(Index, Val, clvMenu)
End Sub

'    --- Check drDrawer Menu
Private Sub clvMenuItems_ItemClick (Index As Int, Value As Object)
    drManager.CLVMenu_ItemClick(Index, Value, clvMenu)
End Sub

Private Sub lblMenuInfo_Resize (Width As Double, Height As Double)
End Sub

Create the menu group and group items​

The menu structure is very simple, the icon code Chr(0xfb2d) is a direct paste of the chosen icon from
Create the menu group and group items:
Public Sub InitMenuMap
    LogPrt($"Create new MenuMap content."$)
    tms.m3Menucompleted = False
'        --- Initialize the OrderedMap
    menuMap.Initialize

'        --- Create here your menu structure
    'Icons taken from materialdesignicons-webfont.ttf please use the bellow tool
    ' https://www.b4x.com/android/forum/threads/b4x-materialicons-web-font-chooser.103985/
'        fnt = xui.CreateFont(LoadWebFont,26)

'        --- First menu group (icon code, text item, status)
    menuList.Initialize
    menuList.Add(CreatemenuType(Chr(0xfb2d), "File", "True"))    ' --- menu Page
    menuList.Add(CreatemenuType(Chr(0xfb2d), "File 1", "True"))
    menuList.Add(CreatemenuType(Chr(0xfd84), "File 2", "FALSE"))
    menuList.Add(CreatemenuType(Chr(0xfb2c), "file 3", "false"))
    menuList.Add(CreatemenuType(Chr(0xfb1c), "File 4", "TRUE"))
    menuList.Add(CreatemenuType(Chr(0xfd84), "file 5", "True"))
    menuList.Add(CreatemenuType(Chr(0xfb1c), "File 6", "TRUE"))
    menuList.Add(CreatemenuType(Chr(0xfd84), "file 7", "True"))
    menuMap.Put("File", menuList)

'        --- Second menu group
    menuList.Initialize
    menuList.Add(CreatemenuType(Chr(0xfd85), "Page", "True"))    ' --- menu Page
    menuList.Add(CreatemenuType(Chr(0xfbbe), "Page Main", "True"))        '--- Crash @@
    menuList.Add(CreatemenuType(Chr(0xfbbe), "Page 1", "True"))
    menuList.Add(CreatemenuType(Chr(0xfb1c), "Page 2", "True"))
    menuList.Add(CreatemenuType(Chr(0xfb1c), "Page 3", "True"))
    menuMap.Put("Page", menuList)

'        --- Second menu group
    menuList.Initialize
    menuList.Add(CreatemenuType(Chr(0xfd85), "Small", "false"))    ' --- menu Page
    menuList.Add(CreatemenuType(Chr(0xfbbe), "Small 1", "True"))
    menuMap.Put("Small", menuList)

'        --- Third menu group
    menuList.Initialize
    menuList.Add(CreatemenuType(Chr(0xf01a), "Config", "True"))    ' --- menu Page
    menuList.Add(CreatemenuType(Chr(0xf01a), "Page 3", "True"))
    menuMap.Put("Config", menuList)

'        --- Fourth menu group
    menuList.Initialize
    menuList.Add(CreatemenuType(Chr(0xf01a), "Menu Tests", "True"))    ' --- menu Tests
    menuList.Add(CreatemenuType(Chr(0xf01a), "Test 1", "True"))
    menuMap.Put("Menu Tests", menuList)
    
'    --- Add more menu groups here

    tms.m3Menucompleted = True
    B4XPages.MainPage.menuMap = menuMap

End Sub
The menu structure is very simple, the icon code Chr(0xfb2d) is a direct paste of the chosen icon from Erel's [B4X] MaterialIcons Web Font Chooser program. Note that the menu group name and group items must be unique to prevent overwriting. The spelling of the status true and false may contain upper and lower case. A False status blocks the use of the menu group or menu item, while the status true is selectable.

Name the m3Menu action to be performed​

Name the m3Menu action to be performed:
Public Sub mainMenu(Index As Int, value As menuType)
    Select value.menuItem
        Case "Page Main"
            B4XPages.ShowPageandRemovePreviousPages("MainPage")
        Case "Page 1"
            B4XPages.ShowPageandRemovePreviousPages("Page1")
        Case "Page 2"
            B4XPages.ShowPageandRemovePreviousPages("Page2")
        Case "Page 3"
            B4XPages.ShowPageandRemovePreviousPages("Page3")
        Case "Test 1"
            B4XPages.ShowPageandRemovePreviousPages("PageTest")
        Case Else
            Drawer.LeftOpen = True
    End Select
End Sub

Set default m3Menu colors​

HTML hexadecimal color code and standard XUI color palette code can be used in the following DrawerManager subroutine:

Set default m3Menu colors:
Public Sub CreateMenuSettings() As menuSettings

    tms.Initialize
    tms.hamburgerIconColor = xui.Color_Blue
    tms.ImageMenuLogoDirectory = $"${File.DirAssets}"$    ' change this to logo directory
    tms.ImageMenuLogoFileName =$"Micro3Logo.png"$        ' change this to your logo file name
    tms.ImageMenuLogoFileName =$"logo.png"$                ' change this to your logo file name
    tms.m3Menucompleted = False
    tms.menuColor = 0xFFF0FFFF                            ' Menu background color
    tms.menuItemColor = 0xFF94D8F6                        ' Menu group items background color
    tms.menuItemDisabledColor = 0xFFF8A1A4                ' Menu disabled option background color
    tms.menuTextColor = xui.Color_Black                    '
    tms.menuWidth = 250dip                                ' Extended horizontal menu width
    tms.MenuHeight = 60dip                                '
    tms.logStatus = False                                ' Logging via logPrt: false = off true = on
    tms.menuInfoText = $"M3Menu                            '
version 1.05"$
    Return tms
End Sub

To quickly implement a so-called own or external house style in all used B4XPages or to be able to adjust it, you can change the value(s) in the subroutine CreateMenuSettings. As already written, you can use the standard xui color palette and HTML color code interchangeably.
The above steps will allow you to use the m3Menu.

Interactivity with the m3Menu​

For those who need more control over the m3Menu, the m3Menu supports the ability to dynamically customize menu groups and menu items.

1740408744031.png


Please note the following limitations:
  1. The behavior of the B4XMainPage is different from the added B4XPage(s). Therefore, do not use an m3Menu with interactivity in the B4XMainPage because the result of the used interactivity is not displayed.

  2. The m3menu configuration is stored as a list in value in a linkedhashmap. See the example of how allowing the previously blocked menu item takes place as an update in this group list. Use the routines present in the #Region M3Menu interactivity:

  3. ResetMenu
    Reset m3Menu to config created by InitMenuMap

  4. ReturnMenuGroupItemsList
    Return all menu items for the given menu group in a list

  5. ChangeMenuGroupltemStatus
    Change the menu item status to the given status true or false. returns logical true if succesfully.

  6. ReturnMenuGroupList
    Return all menu groups in a list

  7. ReturnStatusGivenMenultem
    Return menu status for given menu item

  8. TestMenuGroupNameExist
    Return True if exist, false if unknow menu group name

Frequently Asked Questions (FAQs)​

  1. There are a lot of menus on this site. Why should I use M3Menu?
    M3Menu only shows a few horizontal lines (the "hamburger") on the screen with which a menu can be opened. The opened menu slides from the side over the user screen. This minimizes the space occupied on your program screen.

  2. What does the name M3Memu stand for?
    The "M3" in m3Menu refers to the interchangeable Google terms: "Material 3", "Material design 3", "Material you" and "Compose Material 3" for the color combinations to use in this menu. But don't let that stop you from choosing your own color combination that you like.

  3. Why can I set the "hamburger" icon to a different color than the font color of the menu options?
    This will help you fix a poorly visible 'hamburger' icon with an acceptable combination with your chosen foreground and background colors in M3Menu.

  4. Why is the "hamburger" icon not displayed on a certain B4XPage in B4J, but it is in B4A?
    Possibly the "hamburger" icon is "covered" by another component. By moving that component from the "hamburger" icon location it becomes visible again.

  5. How can I use the M3Menu?
    The M3Menu has been redesigned with Erel's advice to use IDE B4J to easily develop and test in a B4XPages environment in the B4J IDE using B4X components. Then in another IDE you can test via the option "Add Existing Modules" and as "Link - relative path" in the other IDE. I did that for the B4A IDE. By using as many B4X components as possible there are very few differences that are or should be solved via the #IF B4A and #IF B4J options.

  6. Do I need to develop programs with M3Menu in the B4J IDE?
    No, but developing and testing in B4J is easier. In my Proof-Of-Concept program the program models are stored in the project folder. In the B4A IDE these program modules are linked via the option: 'Link - relative path'.
    This setup method ensures that saved adjustments (by hand or at the start of the run command) in one IDE are also automatically implemented in the other IDE. For each IDE you have to manually set the libraries to be used. The Drawer Manager of M3Menu provides the necessary differences between B4J and B4A such as the difference between pane and panel.

  7. How can I display my menu options?
    You can place 1, 2, 3 or more menu options in a menu group. The different menu groups are placed in a vertical scroll list. When you click or touch a menu group, it is expanded and another expanded menu group is collapsed.

  8. How can I customize the menu to my wishes?
    The first configurable InitMenuMap contains the menu groups and the menu items for each group, the second configurable mainMenu defines what the do for each group item (the group name is used to open and close the drop-down list for a menu group), and the third configurable CreateMenuSettings defines the values of the define menu settings Type for consistent implementation of the desired setting across all B4XPage files.

  9. Can I also use M3Menu in the B4XMainPage?
    M3Menu is designed with the "Develop it once, reuse it as much as possible unchanged" principle in mind. This principle facilitates troubleshooting and implementing improvements in programs and the application and reuse of menu groups that are related to a specific reusable B4XPage.

  10. How do I get the character codes for the menu options used?
    The 719 icon character codes come from materialdesignicons-webfont.ttf in the asset directory. Use the tool below
    ' https://www.b4x.com/android/forum/threads/b4x-materialicons-web-font-chooser.103985/ to search through these 719 icons and copy the corresponding character code to the menu option.

  11. Why can't I use a graphic image for a menu option icon?
    The choice for a limited size TTF font makes it easy to adjust the color for a displayed menu line to meet the Material Design 3 requirements.

  12. What makes M3Menu interactive?
    The initial menu configuration is stored in and built from a B4XOrderedMap menuMap in the B4XMainPage. An active menu option has the status "True" in this. By setting this status to "False" the menu option is disabled and displayed with a different chosen background color.
    In the Proof-Of-Concept B4XPageMenuTest page present test routine are examples of how the display and use of the M3Menu are possible.

  13. How can logging be switched on and off?
    DrawerManger has three relevant routines: A global routine logPrt that is switched on with tms.logStatus = True and switched off with the command tms.logStatus =False in the CreateMenuSettings routine. In addition, you can interactively switch logging on with the routine drManager.LogPrintOn and switch logging off again with the routine drManager.LogPrintOff.
Finally, thanks to those who posted all kinds of solutions in this forum that made it possible, in (un)adapted form or not, to develop the m3Menu program and make it available on this forum.
 

Attachments

  • 1740404575703.png
    1740404575703.png
    75.9 KB · Views: 101
Top