Android Tutorial Material Design 3 - Using a ToolBar as ActionBar

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

Google recommends to use a ToolBar instead of the standard system ActionBar for Material Design apps. In this tutorial we will use a ACToolBar(Light/Dark) object from the AppCompat library (1.10 and above) as an ActionBar.

One of the main differences between a ToolBar and the standard ActionBar is that the ActionBar is a system component which is automatically added by the os and a ToolBar is part of our layout so we can add it to the activity with the designer or by code.

Using the ToolBar object

First we need to set up our project like in the Material Design 2 tutorial.
Then we need to add some more items to the theme:

B4X:
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowActionModeOverlay">true</item>

This disables the standard ActionBar in the theme. With the windowActionModeOverlay set to true ActionMode Actionbars will replace the ToolBar and are not displayed above it.

Now we can create our layout. For the example project I decided to split the layout into two parts. One "main" layout which contains the ToolBar and a simple Panel for the content.
So add a CustomView of type "ACToolBarLight" to a new layout called "main" and set the following properties:

Layout_ActionBar.png


Note that "Use as main ActionBar" is checked to use this Toolbar as the main ActionBar for the Activity. You can only use one Toolbar as the Activity ActionBar.
Elevation should be set to 4 for a normal ActionBar. This will produce a small shadow below it.
Additionally you should disable the Background color in the properties.

There are two versions of the ToolBar object. ACToolBarLight uses a light theme and ACToolBarDark uses a dark theme by default. This is only for historical reasons. You can set the light or dark theme for the ToolBar and the overflow menu with the designer properties now.

Now we add a Panel named pContent to the Layout with the following properties:

Layout_pContent.png


Because the standard height of the ToolBar/ActionBar in Material Design depends on the device orientation and screen size we add a small designer script:
B4X:
If ActivitySize > 6.5 Then
  ActionBar.Height = 64dip
Else
  If Portrait Then
    ActionBar.Height = 56dip
  Else
    ActionBar.Height = 48dip
  End If
End If

pContent.SetTopAndBottom(ActionBar.Bottom, 100%y)
This will set the ActionBar height to 64dip on tablets and to 56dip on portrait phones and 48dip on landscape phones. These specifications are in the Material Design guide.

Now we have a minimal example of how to setup a ToolBar as an ActionBar.

ToolBar_Shadow.png


Misc stuff

You can use the ACActionBar object to control some ActionBar features like showing the "Up" indicator arrow.

B4X:
Dim ABHelper as ACActionBar

ABHelper.ShowUpIndicator = True

Adding actions and overflow menu

You can use the normal Activity.AddMenuItem() methods to add a menu or actions to the ToolBar:

B4X:
Dim xml As XmlLayoutBuilder
Dim bd As BitmapDrawable
bd = xml.GetDrawable("ic_plus_one_black_24dp")
Activity.AddMenuItem3("Plus one", "Menu", bd.Bitmap, True)
bd = xml.GetDrawable("ic_refresh_black_24dp")
Activity.AddMenuItem3("Refresh", "Menu", bd.Bitmap, True)
Activity.AddMenuItem("Overflow1", "Menu")
Activity.AddMenuItem("Overflow2", "Menu")
Activity.AddMenuItem("Overflow3", "Menu")

I prefer to use drawables for action icons than use the LoadBitMap() function. The drawables are available in different resolutions and will always load in the perfect size for your device. To load drawables you will have to use the XmlLayoutBuilder library.

The attached example has some UI elements to control some features of the ToolBar. Have fun with it.

ExampleApp.png
 

Attachments

  • ACToolBarExample2_0.zip
    25.3 KB · Views: 3,739
Last edited:

frenkipi

Member
Licensed User
Longtime User
Hello guys, I have managed material design 2 to get to work, but now I am stucked with this example...
I don't know which folder or files do I have to use for

B4X:
#AdditionalRes: C:\Users\stm\Dropbox\Basic4Android\CustomLibsRes\b4a_appcompat, de.amberhome.objects.appcompat

Or is this path for a layout folder in project example?

Is this the path for appcompact library? Because I already have it in path configuration for additional libraries?

Thank you.
 

corwin42

Expert
Licensed User
Longtime User
B4X:
#AdditionalRes: C:\Users\stm\Dropbox\Basic4Android\CustomLibsRes\b4a_appcompat, de.amberhome.objects.appcompat

Or is this path for a layout folder in project example?

Is this the path for appcompact library? Because I already have it in path configuration for additional libraries?

As Erel said this is not needed anymore.

I'm currently updating the Material Design tutorials. 1+2 are updated for the latest B4A 6.0 and latest AppCompat 3.20 wrapper and the examples should work without problems. I hope that I will have Tutorial 3 (this one) ready tomorrow.

Note, that some properties for the Toolbar can now be set with the Designer (as "SetAsActionBar").
 

frenkipi

Member
Licensed User
Longtime User
Thank you all for your fast response.

On example project I am getting an error. I am using android SDK build tools rev 23.0.3, android support repository rev 35. What are you suggesting?

** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = true **
Error occurred on line: 44 (Main)
java.lang.RuntimeException: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Object.equals(java.lang.Object)' on a null object reference
at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:166)
at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:209)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:703)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:340)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at de.amberhome.appcompat.toolbarexample1.main.afterFirstLayout(main.java:102)
at de.amberhome.appcompat.toolbarexample1.main.access$000(main.java:17)
at de.amberhome.appcompat.toolbarexample1.main$WaitForLayout.run(main.java:80)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Object.equals(java.lang.Object)' on a null object reference
at de.amberhome.objects.appcompat.ACToolBarWrapper.DesignerCreateView(ACToolBarWrapper.java:74)
at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:70)
at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:158)
... 20 more
** Activity (main) Resume **
** Activity (main) Resume **


Regards!
 

corwin42

Expert
Licensed User
Longtime User
On example project I am getting an error. I am using android SDK build tools rev 23.0.3, android support repository rev 35. What are you suggesting?

Open the designer, load the layout file, save it again, retry.
 

JohnC

Expert
Licensed User
Longtime User
What you want is a light theme with a dark toolbar.

Do the following:

  1. Use Theme.AppCompat.Light.DarkActionBar as your parent theme. You don't need to use a NoActionBar theme because this is done with the windowActionBar:false item.
  2. Use ACToolBarDark as your Toolbar
  3. Set your Toolbar.PopupTheme to Light.
If you use the designer to add your Toolbar (the recommended method now) then it doesn't matter if you use a light or dark toolbar. You can set the Toolbar Theme and Popup Theme in the designer properties.

That worked great - thanks for responding quickly!
 

Roberto P.

Well-Known Member
Licensed User
Longtime User
how to intercept event from the bitmap icon added with NavigationIconBitmap ?
thank you
 

corwin42

Expert
Licensed User
Longtime User
how to intercept event from the bitmap icon added with NavigationIconBitmap ?
thank you

If you have a menu added to your app you can use
B4X:
Sub Activity_ActionBarHomeClick

    
End Sub

If you don't have a Menu in your app you have to call ToolBar.InitMenuListener and use this event:
B4X:
Sub ToolBar_NavigationItemClick

End Sub
 

Lahksman

Active Member
Licensed User
Longtime User
If I'm not mistaken it's the following. Under point Misc in the first post.

You can use the ACActionBar object to control some ActionBar features like showing the "Up" indicator arrow.
B4X:
Dim ABHelper as ACActionBar

ABHelper.ShowUpIndicator = True
 

Roberto P.

Well-Known Member
Licensed User
Longtime User
If you have a menu added to your app you can use
B4X:
Sub Activity_ActionBarHomeClick

   
End Sub

If you don't have a Menu in your app you have to call ToolBar.InitMenuListener and use this event:
B4X:
Sub ToolBar_NavigationItemClick

End Sub

Ok. Thanks your and Best regards
 

luke2012

Well-Known Member
Licensed User
Longtime User
Hi @corwin42. First of all my compliments for this wonderful and useful tutorial :)

I state that: "I like very much the look & feel of this actionbar" :)
But a have a couple of little question:

1)This is the only (available) solution to build a Material Design ActionBar in B4A ?
2) There is also a Navigation Drawer (material design) tutorial / solution ?

Thanks in advance for your reply!
 
Last edited:

corwin42

Expert
Licensed User
Longtime User
2) There is also a Navigation Drawer (material design) tutorial / solution ?
2) @corwin42 is working on a drawer. Don´t know whether of it´s actual state. Just read a few days ago he´s working on it...

The next version of the DesignSupport library will have a wrapper for the DrawerLayout and NavigationView. It will be totally conform with the material design guide (displays below (transparent) StatusBar but above ToolBar etc.)
For a Screenshot see here.

If I don't find any fatal bugs it will be released (end of) next week. Most work now is testing it with older Android Versions.
 

luke2012

Well-Known Member
Licensed User
Longtime User
The next version of the DesignSupport library will have a wrapper for the DrawerLayout and NavigationView. It will be totally conform with the material design guide (displays below (transparent) StatusBar but above ToolBar etc.)
For a Screenshot see here.

If I don't find any fatal bugs it will be released (end of) next week. Most work now is testing it with older Android Versions.

Wow @corwin42 ! It's fantastic! :)
 

beeblomarv

Member
Licensed User
Longtime User
Note: You should use B4A 6.0 or above for this tutorial.

Google recommends to use a ToolBar instead of the standard system ActionBar for Material Design apps. In this tutorial we will use a ACToolBar(Light/Dark) object from the AppCompat library (1.10 and above) as an ActionBar.

One of the main differences between a ToolBar and the standard ActionBar is that the ActionBar is a system component which is automatically added by the os and a ToolBar is part of our layout so we can add it to the activity with the designer or by code.

Using the ToolBar object

First we need to set up our project like in the Material Design 2 tutorial.
Then we need to add some more items to the theme:

B4X:
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowActionModeOverlay">true</item>

This disables the standard ActionBar in the theme. With the windowActionModeOverlay set to true ActionMode Actionbars will replace the ToolBar and are not displayed above it.

Now we can create our layout. For the example project I decided to split the layout into two parts. One "main" layout which contains the ToolBar and a simple Panel for the content.
So add a CustomView of type "ACToolBarLight" to a new layout called "main" and set the following properties:

View attachment 46540

Note that "Use as main ActionBar" is checked to use this Toolbar as the main ActionBar for the Activity. You can only use one Toolbar as the Activity ActionBar.
Elevation should be set to 4 for a normal ActionBar. This will produce a small shadow below it.
Additionally you should disable the Background color in the properties.

There are two versions of the ToolBar object. ACToolBarLight uses a light theme and ACToolBarDark uses a dark theme by default. This is only for historical reasons. You can set the light or dark theme for the ToolBar and the overflow menu with the designer properties now.

Now we add a Panel named pContent to the Layout with the following properties:

View attachment 30935

Because the standard height of the ToolBar/ActionBar in Material Design depends on the device orientation and screen size we add a small designer script:
B4X:
If ActivitySize > 6.5 Then
  ActionBar.Height = 64dip
Else
  If Portrait Then
    ActionBar.Height = 56dip
  Else
    ActionBar.Height = 48dip
  End If
End If

pContent.SetTopAndBottom(ActionBar.Bottom, 100%y)
This will set the ActionBar height to 64dip on tablets and to 56dip on portrait phones and 48dip on landscape phones. These specifications are in the Material Design guide.

Now we have a minimal example of how to setup a ToolBar as an ActionBar.

View attachment 30936

Misc stuff

You can use the ACActionBar object to control some ActionBar features like showing the "Up" indicator arrow.

B4X:
Dim ABHelper as ACActionBar

ABHelper.ShowUpIndicator = True

Adding actions and overflow menu

You can use the normal Activity.AddMenuItem() methods to add a menu or actions to the ToolBar:

B4X:
Dim xml As XmlLayoutBuilder
Dim bd As BitmapDrawable
bd = xml.GetDrawable("ic_plus_one_black_24dp")
Activity.AddMenuItem3("Plus one", "Menu", bd.Bitmap, True)
bd = xml.GetDrawable("ic_refresh_black_24dp")
Activity.AddMenuItem3("Refresh", "Menu", bd.Bitmap, True)
Activity.AddMenuItem("Overflow1", "Menu")
Activity.AddMenuItem("Overflow2", "Menu")
Activity.AddMenuItem("Overflow3", "Menu")

I prefer to use drawables for action icons than use the LoadBitMap() function. The drawables are available in different resolutions and will always load in the perfect size for your device. To load drawables you will have to use the XmlLayoutBuilder library.

The attached example has some UI elements to control some features of the ToolBar. Have fun with it.

View attachment 30937






I am getting this error:


B4A version: 5.80
Parsing code. (0.00s)
Compiling code. (0.03s)
Compiling layouts code. (0.01s)
Generating R file. Error
res\values\themes.xml:3: error: Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCompat.Light.DarkActionBar'.
res\values\themes.xml:6: error: Error: No resource found that matches the given name: attr 'colorAccent'.
res\values\themes.xml:4: error: Error: No resource found that matches the given name: attr 'colorPrimary'.
res\values\themes.xml:5: error: Error: No resource found that matches the given name: attr 'colorPrimaryDark'.
res\values\themes.xml:8: error: Error: No resource found that matches the given name: attr 'windowActionBar'.
res\values\themes.xml:9: error: Error: No resource found that matches the given name: attr 'windowActionModeOverlay'.
res\values\themes.xml:7: error: Error: No resource found that matches the given name: attr 'windowNoTitle'.
 
Top