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

ArminKH

Well-Known Member
as you can see at following link this attribute will not works on android 16 and lower
http://stackoverflow.com/questions/27875704/warning-for-androidsupportsrtl-in-androidmanifest
android:supportsRtl Declares whether your application is willing to support right-to-left (RTL) layouts. If set to true and targetSdkVersion is set to 17 or higher, various RTL APIs will be activated and used by the system so your app can display RTL layouts. If set to false or if targetSdkVersion is set to 16 or lower, the RTL APIs will be ignored or will have no effect and your app will behave the same regardless of the layout direction associated to the user's Locale choice (your layouts will always be left-to-right). The default value of this attribute is false. This attribute was added in API level 17
 
Last edited:

corwin42

Expert
Licensed User
Longtime User
is this working on all android version?
and if our device language be english but our app's language be for example persian then this attribute works?

Android supports this from API 17 (4.2 Jelly Bean) so it is working on about 80% of all android devices.
Of course this works only if the device language is set to an RTL language (or you enable force RTL for all languages in developer settings).

You cannot reverse the order of the items in the ToolBar/ActionBar manualy. The only other thing that you can do is to call android.support.v4.view.ViewCompat.setLayoutDirection() via reflection library (or JavaObject). Set it to LAYOUT_DIRECTION_RTL (1) to force a RTL layout.
With this you will be able to set the direction for views individually.

But I guess this will only work on API17+, too. I haven't tried it.
 

ArminKH

Well-Known Member
Android supports this from API 17 (4.2 Jelly Bean) so it is working on about 80% of all android devices.
Of course this works only if the device language is set to an RTL language (or you enable force RTL for all languages in developer settings).

You cannot reverse the order of the items in the ToolBar/ActionBar manualy. The only other thing that you can do is to call android.support.v4.view.ViewCompat.setLayoutDirection() via reflection library (or JavaObject). Set it to LAYOUT_DIRECTION_RTL (1) to force a RTL layout.
With this you will be able to set the direction for views individually.

But I guess this will only work on API17+, too. I haven't tried it.
corwin here is my code
B4X:
For i = 0 To AppCompatToolbar.NumberOfViews -1
     AppCompatToolbar.GetView(i).Left = 100%x - AppCompatToolbar.GetView(i).Left - AppCompatToolbar.GetView(i).Width
Next
if the left position(and width) of each item be available then we can change action bar gravity to right to left by using above code but when i use this code log messages say for example "(ImageButton): Layout not available" and this message
upload_2015-8-18_16-31-35.png

have u any suggestion? because i cant limit my app just for api 17+
and if i want to use my custom toolbar(which i make it with 1 panel and image view and label ,...) then i can't use some future such as search view , ACMenu , ...
 
Last edited:

corwin42

Expert
Licensed User
Longtime User
corwin here is my code
B4X:
For i = 0 To AppCompatToolbar.NumberOfViews -1
     AppCompatToolbar.GetView(i).Left = 100%x - AppCompatToolbar.GetView(i).Left - AppCompatToolbar.GetView(i).Width
Next
if the left position(and width) of each item be available then we can change action bar gravity to right to left by using above code but when i use this code log messages say for example "(ImageButton): Layout not available" and this message

have u any suggestion? because i cant limit my app just for api 17+
and if i want to use my custom toolbar(which i make it with 1 panel and image view and label ,...) then i can't use some future such as search view , ACMenu , ...

What you are trying to do is not possible. The layout of the Toolbar is not made of B4A Views. It has a complex layout which is defined in the AppCompat resources. You can't modify it with this simple B4A methods.

The solution I suggested is the only way which is supported by Android directly. If you need it for API level 16 and below you have to implement your own custom ToolBar/ActionBar which can handle this.
 

ArminKH

Well-Known Member
What you are trying to do is not possible. The layout of the Toolbar is not made of B4A Views. It has a complex layout which is defined in the AppCompat resources. You can't modify it with this simple B4A methods.

The solution I suggested is the only way which is supported by Android directly. If you need it for API level 16 and below you have to implement your own custom ToolBar/ActionBar which can handle this.
then i can't use appcompat future such as search view or ACMenu in my custom toolbar
is this possible? at least for search view
i asked this question on this thread
https://www.b4x.com/android/forum/threads/using-app-combat-search-view-in-our-custom-toolbar.57184/
but still not answered
 

Firpas

Active Member
Licensed User
Longtime User
Great work corwin42 !!

Is it possible to change the icon for an item on the fly ??

Is it possible to use an togglebutton?

Regards
 

corwin42

Expert
Licensed User
Longtime User
Is it possible to change the icon for an item on the fly ??

Is it possible to use an togglebutton?

1. I think what you are searching for is explained here.

2. A ToggleButton may be added as a CustomView but I haven't tried it.
 

Tom1s

Member
Licensed User
Longtime User
Hi

I would like to change the color of one of the icons in the actionbar. Can I do that somehow? I tried to switch the picture in the program but no success.
I try to make like ON and OFF signs.

EDIT: There is same question above....so i try to look there.
 

Tom1s

Member
Licensed User
Longtime User
There was only menu item change. How about the icons in actionbar?

Got it this way like in appcompat 4 tutorial. Don't know if it is right but it seemed to be working
B4X:
Dim item As ACMenuItem
    Menu.Add2(20, 1, "Refresh", xml.GetDrawable("ic_refresh_red_24dp")).ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
    Menu.Add2(10, 1, "Refresh", xml.GetDrawable("ic_refresh_black_24dp")).ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
   

    'Sync Checkboxes with the Menu
    SetCheckBoxState(Menu)
    ToolBar.Menu.finditem(20).Visible=False
    ToolBar.Menu.finditem(10).Visible=True

And then playing with visible=false/true in the code.
 

corwin42

Expert
Licensed User
Longtime User
You can use one item and change the icon at runtime like this:

B4X:
ToolBar.Menu.FindItem(1).Icon = xml.GetDrawable("ic_refresh_red_24dp")
 

joneden

Active Member
Licensed User
Longtime User
Great lib corwin42 and great docs too.

I've just found the MSIconicDrawable lib & fonts. Is it possible to integrate them instead of using icon files? I've tried the following and while it doesn't crash the app it also doesn't display anything :(

The commented bit at the bottom is the original code. It would be great to be able to the the font as that would make things a lot easier - not having to worry about icons.

Thanks for any pointers

Jon

B4X:
Dim item As ACMenuItem
    Dim iconBinTracking As MSIconicDrawable : iconBinTracking.Initialize("gmd_sync")          : iconBinTracking.Color = 0xffffff00
    Menu.Add2(1, 1, "Sync",  iconBinTracking.Drawable).ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
    'Menu.Add2(1, 1, "Sync",  objXmlLayoutBuilder.GetDrawable("ic_sync_white_24dp")).ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
 

Anser

Well-Known Member
Licensed User
Longtime User
I've just found the MSIconicDrawable lib & fonts. Is it possible to integrate them instead of using icon files?

It would be great to be able to use the font as that would make things a lot easier - not having to worry about icons.

Thanks for any pointers

Jon
I would also love to have this feature :)
It would help to avoid lot of unnecessary troubles regarding icon images, its colors, resolutions etc etc. Just one single font file in the app, Wow.

Regards
Anser
 

joneden

Active Member
Licensed User
Longtime User
I just came back to the msiconicdrawable setup and it works perfectly. Code for my setup is below

B4X:
    uxActionBar.SetAsActionBar
    uxActionBar.Title = "Dashboard"
    Dim icon As MSIconicDrawable : icon.Initialize("gmd_menu")      : icon.Color = Colors.white
    icon.actionBarSize
    uxActionBar.NavigationIconDrawable = icon.Drawable

and in the menu setup pretty much the same thing again

B4X:
Dim item As ACMenuItem
    Dim icon As MSIconicDrawable : icon.Initialize("gmd_sync")      : icon.Color = Colors.white
    icon.actionBarSize
    Menu.Add2(1, 1, "Sync",  icon.Drawable).ShowAsAction = item.SHOW_AS_ACTION_ALWAYS

This is great as it really cuts out a massive amount of hassle using icons. I've now used this in a variety of places in my code and the simplification is great :)
 

phukol

Active Member
Licensed User
Longtime User
Hi there guys, i seem to have issues in showing the msicondrawable? im trying to run the example in MSMaterialDrawer example but all i get is this. No icon is shown? what could be the issue? Also is it possible if i just use a typeface for the drawable instead of using msiconic?
 

Attachments

  • Untitled.png
    Untitled.png
    80.2 KB · Views: 632

phukol

Active Member
Licensed User
Longtime User
sorry DonManFred..... Thanks for the reply.... i will move my question to the msiconic thread.
 
Top