Android Tutorial Material Design 4 - Modifyable and advanced Menu

Note: You should use B4A 6.0 or above for this tutorial.

With the ACToolBar(Light|Dark) object we can get access to the Menu object of the activity. This opens the possibility for modifyable menus and some other advanced menu features.

Basics

With the ToolBar.Menu property we have access to the menu of the ToolBar. For a standalone ToolBar (which is not set as the activity ActionBar) we can just access the property everywhere in our code and do what we want to do with it just like adding/removing menu items.

If the ToolBar is our activities ActionBar we have to handle the menu in a special way because if we don't do this, B4As own menu handling will conflict with our handling.

In Android the menu is created and initalized with two methods: onCreateOptionsMenu() and onPrepareOptionsMenu(). I don't want to explain the whole menu system here you just need to know, that B4A uses these methods internally to create it's own menu and they get called "at some time" in the activity initialization process.

With the itroduction of inline Java code in B4A 4.30 we now have the possibility to add our own code to handle the application menu. The idea is to call an event to set up the menu and here is an example how this can be done:

B4X:
#If Java

public boolean _onCreateOptionsMenu(android.view.Menu menu) {
    if (processBA.subExists("activity_createmenu")) {
        processBA.raiseEvent2(null, true, "activity_createmenu", false, new de.amberhome.objects.appcompat.ACMenuWrapper(menu));
        return true;
    }
    else
        return false;
}
#End If

In this code we use the _onCreateOptionsMenu hook to check if a Sub named "Activity_CreateMenu" exists. If yes, then we call it and we provide the activities menu as a parameter. If the sub does not exist, the normal B4A menu-handling is done.

Now we need the implementation of Activity_CreateMenu:

B4X:
Sub Activity_CreateMenu(Menu As ACMenu)
    Menu.Clear

    Dim item As ACMenuItem
    Menu.Add2(10, 1, "Plus one", xml.GetDrawable("ic_plus_one_black_24dp")).ShowAsAction = item.SHOW_AS_ACTION_IF_ROOM
    Menu.Add2(20, 2, "Refresh", xml.GetDrawable("ic_refresh_black_24dp")).ShowAsAction = item.SHOW_AS_ACTION_ALWAYS

    Menu.Add(1, 3, "Overflow1", Null)
    Menu.Add(2, 4, "Overflow2", Null)
    Menu.Add(3, 5, "Overflow3", Null)

    'Sync Checkboxes with the Menu
    SetCheckBoxState(Menu)

End Sub
First we clear the menu to be sure that there are no old entries in it. Then we just use the Menu object to add some additional menus. Easy, isn't it? (For this example we sync the menu with the checkboxes with SetCheckBoxState())

It is good practice to use a Toolbar as your ActionBar. If you do this you can access the menu with ToolBar.Menu everywhere in your code to modify the menu.

Some advanced menu features

With the ACMenu and ACMenuItem objects we have access to some advanced menu features.

When you add a menu item to the menu you can specify a menu ID and a sort order. So with the sort order you can later add menu entries which are displayed above other menu items. With the ID you can access this item later and modify it.

You can create checkable menu itemes. The ACMenu.Add() methods return the added menu item so you can directly modify it and make it checkable or set it as an action item or even make it invisible.

It is even possible to add or remove menu items dynamically.

B4X:
Sub cbItemVisible_CheckedChange(Checked As Boolean)
  ToolBar.Menu.FindItem(1).Visible = Checked
End Sub

Sub cbItemCheckable_CheckedChange(Checked As Boolean)
  ToolBar.Menu.FindItem(2).Checkable = Checked
End Sub

Sub cbItemDisable_CheckedChange(Checked As Boolean)
  ToolBar.Menu.FindItem(3).Enabled = Not(Checked)
End Sub

Look at the example project for better understanding.

overflow_menu.png
 

Attachments

  • ToolBarMenuExample2_0.zip
    18.6 KB · Views: 4,162
Last edited:

shashkiranr

Active Member
Licensed User
Longtime User
Hi @andre.astafieff

You need to go to developer options and check unknown sources that allows you to install non market apps. To activate developer options click on Build Number multiple times until you get a toast message saying developer options activated.

Also copy the error message and post it so that it will be more clear.

Hope this helps.

Regards,
SK
 

corwin42

Expert
Licensed User
Longtime User
We need more info.

How is the device connected? You only will see a log output in unfiltered logs when your device is connected via usb.

If you can't get a log output maybe you can send me the apk or better put it somewhere where i can download it from.
 
Last edited:

corwin42

Expert
Licensed User
Longtime User
Updated the example in the first post. It now includes the missing resources folder. Please download it again.

Didn't B4A report an error about the missing folder? The #AdditionalRes: ..\resources line should give an error.
 

corwin42

Expert
Licensed User
Longtime User
Thanks !!!

I am connected via wifi for B4A-Bridge.

To see the error stack for this issue you must connect your device with USB and then it will show up in the unfiltered logs. If you can't connect a real device with USB you can also try the Android emulator or better Genymotion.
 

andre.astafieff

Member
Licensed User
Longtime User
This is great stuff again @corwin42, thank you. I do have two questions.

1. How can I change the color of the Up Indicator to white from black?
2. Is it possible to capture the Up Indicator click event, I've tried everything that has crossed my mind and I've failed miserably?

Yes I've been busy integrating AppCompat 1.10 into a new app of mine, please look at the screen shot below to see my Up Indicator color issue.
View attachment 30995


Cheers...


Hello @Peter Simpson

Could you tell me how prepared the side menu (left)?
 

Peter Simpson

Expert
Licensed User
Longtime User

ArminKH

Well-Known Member
I will probably change the app to utilise this library instead
yes thats very useful lib and we can create a side menu just in 5 6 line,but thats not customizable such as font of items ,item gravity,icon gravity, etc...
totally thats just is suitable for english language drawers
 

ArminKH

Well-Known Member
You can create a sliding menu yourself in just five lines, okay this I have to see, show me that code @arminkh...
B4X:
Sub CreateMainLayout
    Dim MDB As MSMaterialDrawerBuilder,MD As MSMaterialDrawer
        MDB.Initialize("MD")
        MDB.AddPrimaryDrawerItem  ("Home"  , Null ,Null ,"+99" ,True,1, "")
        MDB.AddSecondaryDrawerItem("Setting" ,Null ,Null ,""    ,True ,2)
        MD = MDB.Build   
End Sub
this is simplest code which we can use for creating drawer just in 5 line:D;)
@Peter Simpson
 

Peter Simpson

Expert
Licensed User
Longtime User
@arminkh you said that you could write one in 5 lines, that is not writing one in 5 lines, that is utilising a library, not you writing one. Anyway this is the wrong thead to have this discussion...
 
Last edited:

ArminKH

Well-Known Member
@arminkh you said that you could write one in 5 lines, that is not writing one in 5 lines, that is utilising a library, not you writing one. Anyway this is the wrong thead to have this discussion...
Oooops!!!
Excuse me if my bad english makes misunderstanding !!!
But i said we can create a drawer just with 5 6 line !!!!
 

andre.astafieff

Member
Licensed User
Longtime User
Hi @corwin42



I'm finally getting to integrate with MSMaterialDrawer (https://www.b4x.com/android/forum/threads/msmaterialdrawer.53883/#content), but now I have one doubt beginner.

When you open the application realized that loads the main Activity with the member sign that code loads the layout "main" later other content is uploaded to a Panel as if we were working with an iFrame in html.

Now I'm adapting an application that was already in development operating with Activitys and conjugated layouts (each layout had its codification in a module Activity type) how I could adapt my code to when I load the layouts in the panel can operate with the logic part?
 

ArminKH

Well-Known Member
hi @corwin42
Is there any way to change menu indicator to White with AcToolbarLight?
i don't want to use AcTollbarDark at all because then my OverFlow menu items background color be dark and thats seem not good for my app
thank u
 

fishwolf

Well-Known Member
Licensed User
Longtime User
If i use the example on page 1, i get this error to start

08-17 11:53:03.675: I/B4A(15274): ~i:** Activity (main) Create, isFirst = true **
08-17 11:53:03.725: I/B4A(15274): ~e:java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

how to i can fix?
 

corwin42

Expert
Licensed User
Longtime User
hi @corwin42
Is there any way to change menu indicator to White with AcToolbarLight?
i don't want to use AcTollbarDark at all because then my OverFlow menu items background color be dark and thats seem not good for my app
thank u

I never tried it but you may change it in the theme file.

A better solution is to set the Theme for the OverFlow menu:

B4X:
ActionBar.PopupTheme = ActionBar.THEME_DARK

If i use the example on page 1, i get this error to start

08-17 11:53:03.675: I/B4A(15274): ~i:** Activity (main) Create, isFirst = true **
08-17 11:53:03.725: I/B4A(15274): ~e:java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

how to i can fix?

Can you provide more info. What device are you trying it on (Android version)? Can you post the complete error stack trace?
 

Inman

Well-Known Member
Licensed User
Longtime User
Is it possible to create a popup menu and display it when a button on the activity is pressed? And if possible display the menu on top of the button so that the context will be clear for the user.
 
Top