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,787
Last edited:

Ian Garton

Member
Licensed User
Longtime User
But if I add action items as menu items, will I be able to selectively show/hide it when needed? I have your ViewPager in the Activity and when the user swipes to different pages, I need to show and hide certain items on toolbar based on the CurrentPage.

I'm having similar issues. Activity.AddMenu is no good as there doesn't appear to be any method to remove or hide menu items.
ActionBar.Menu looks like it has the required methods, but I'm unable to make a menu appear on the ACToolBar.
 

KL7000F

Member
Licensed User
Longtime User
Hello,

if I use this example it works just fine! But when I use Notification and there use colored icons, then they will not appear on Android 5 in color.

Screenshots:
Screenshot_2015-04-21-18-34-34.png
Screenshot_2015-04-21-18-34-46.png

How do I solve this "problem"?

greeting
Andy
 
Last edited:

RandomCoder

Well-Known Member
Licensed User
Longtime User
This is the new Material way of showing the notification icon, see here for guidance...
http://developer.android.com/design/style/iconography.html#notification

Reading this from Google doc's it appears as though any icon you choose will be used as a mask to create the white notification icon...
Don't

Place any additional alpha (dimming or fading) into your small icons and action icons; they can have anti-aliased edges, but because Android uses these icons as masks (that is, only the alpha channel is used), the image should generally be drawn at full opacity.

Don't

Use color to distinguish your app from others. Notification icons should only be a white-on-transparent background image.
Maybe there is a way to change this behaviour but then you would be going against the Material guidelines :eek:
 

woniol

Active Member
Licensed User
Longtime User
Hi,
I would like to change ActionBar color between Activities.
Is it possible to change it's color in code?
I would appreciate some examples if it's possible.

Maciej
 

corwin42

Expert
Licensed User
Longtime User
Hi,
I would like to change ActionBar color between Activities.
Is it possible to change it's color in code?
I would appreciate some examples if it's possible.
Since this tutorial is about the ToolBar you can use just the Color attribute of the ACToolBarLight or ACToolBarDark Toolbars.
 

fgrdovic21

Member
Licensed User
Longtime User
Hello to ya all

Unfortunately, I'm unable to make my app work. It won't even start.
On load, it instantly crashes with no errors in log. It displays message: "Unfortunately, app has stopped".
Here's my code:

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

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

#AdditionalRes: ..\resource
#AdditionalRes: D:\Programs\Basic4android\Libraries\b4a_appcompat, de.amberhome.objects.appcompat
#AdditionalRes: D:\Programs\Android\extras\android\support\v7\appcompat\res, android.support.v7.appcompat
#Extends: android.support.v7.app.ActionBarActivity

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.

    Private ActionBar As ACToolBarLight
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")
    ActionBar.SetAsActionBar

    'Set Title and Subtitle for the ToolBar
    ActionBar.Title = "AppCompat"
    ActionBar.SubTitle = "ToolBar Example 1"
  
    Dim AC As AppCompat
    AC.SetElevation(ActionBar, 8dip)
  
    'Dim ABHelper As ACActionBar
    'ABHelper.Initialize
    'ABHelper.ShowUpIndicator = True
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Layout "Main" is set the same way the tutorial shows.
This is theme.xml

B4X:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="Teal" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">#009688</item>
        <item name="colorPrimaryDark">#00897B</item>
        <item name="colorAccent">#009688</item>
        <item name="android:windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
    </style>
</resources>

I've been searching for this error last two days and was unable to find solution. This happens on LG Optimus G running Android 5.1.1 CyanogenMod 12.1 and Samsung Galaxy Tab 3 running stock Android 4.4.2. Any help is really appreciated. Thanks!
 

fgrdovic21

Member
Licensed User
Longtime User
Where are the logs?

The thing is that they don't show anything:

B4X:
Installing file.
** Activity (main) Pause, UserClosed = false **
PackageAdded: package:com.serbapp.app
** Activity (main) Resume **

This is without filter checked:

B4X:
LogCat connected to: B4A-Bridge: LGE LG-E975
--------- beginning of main
** Activity (main) Resume **
Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
Timeline: Activity_idle id: android.os.BinderProxy@3d3d382f time:17964435
** Service (service1) Destroy **
Ignoring event as service was destroyed: server_newconnection
** Service (service1) Create **
** Service (service1) Start **
Connected to B4A-Bridge (Wifi)
Installing file.
** Activity (main) Pause, UserClosed = false **
PackageAdded: package:com.serbapp.tunora
** Activity (main) Resume **
Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
Timeline: Activity_idle id: android.os.BinderProxy@3d3d382f time:18024125
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **
Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
Timeline: Activity_idle id: android.os.BinderProxy@3d3d382f time:18038336
Installing file.
** Activity (main) Pause, UserClosed = false **
PackageAdded: package:com.serbapp.tunora
** Activity (main) Resume **
Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
Timeline: Activity_idle id: android.os.BinderProxy@3d3d382f time:18154647
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **
Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
Timeline: Activity_idle id: android.os.BinderProxy@3d3d382f time:18167263
 

corwin42

Expert
Licensed User
Longtime User
The thing is that they don't show anything:

B4X:
Installing file.
** Activity (main) Pause, UserClosed = false **
PackageAdded: package:com.serbapp.app
** Activity (main) Resume **

This is without filter checked:

B4X:
LogCat connected to: B4A-Bridge: LGE LG-E975
--------- beginning of main

Try to connect your devices via USB. This should show the error in the unfiltered logs.

Please post your Manifest.
 

fgrdovic21

Member
Licensed User
Longtime User
Try to connect your devices via USB. This should show the error in the unfiltered logs.

Please post your Manifest.

Manifest:
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.b4x.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="22"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'SetApplicationAttribute(android:theme, "@android:style/Theme.Holo")
SetApplicationAttribute(android:theme, "@style/Teal")
'End of default text.

The thing is, I'm using Windows 10 and ADB Driver is not compatible with it. I don't know if its a B4A bug or Windows , but B4A cannot find my device, thus I'm forced to use B4A Bridge.
 

thedesolatesoul

Expert
Licensed User
Longtime User
The thing is, I'm using Windows 10 and ADB Driver is not compatible with it. I don't know if its a B4A bug or Windows , but B4A cannot find my device, thus I'm forced to use B4A Bridge.
Probably a windows bug. Also, you could try running it on genymotion to get the logs.
 

kmap

Member
Licensed User
Longtime User
i get this error java.lang.RuntimeException: Unable to start activity ComponentInfo{my.book/my.book.main}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content

Regrads
 
Top