B4A Library StdActionBar - Another ActionBar library

StdActionBar (Standard ActionBar) library is based on the native ActionBar API, therefore it is only supported by Android 4+.

StdActionBar / StdViewPager tutorial: ActionBar / Sliding Pages tutorial

The share of Android 2.x devices is dropping and currently (January 2014) it is only 24%.

This library allows you to add tabs and dropdown list to the action bar:

upload_2014-1-16_17-20-37.png
upload_2014-1-16_17-21-7.png


The attached example demonstrates both modes. You should change the navigation mode to see the two modes.

List mode

Adding a list is very simple. You set the NavigationMode:
B4X:
bar.NavigationMode = bar.NAVIGATION_MODE_LIST
Add the items:
B4X:
bar.SetListItems(Array As String("Dropdown 1", "Dropdown 2", "Dropdown 3"))

And handle the event:
B4X:
Sub bar_ListItemSelected (Index As Int, Value As String)
   Log("Selected value: " & Value)
End Sub

Tabs mode

Unlike TabHost, the tabs do not hold any views. You are responsible for switching the layout based on the selected tab.

The first step is to set the navigation mode:
B4X:
bar.NavigationMode = bar.NAVIGATION_MODE_TABS

Then we add the tabs:
B4X:
bar.AddTab("Tab 1")
bar.AddTab returns a StdTab object. We can use it to modify the tabs:
B4X:
bar.AddTab("Tab 1").Tag = panel1
bar.AddTab("Tab 2").Tag = panel2
'Add icon to tab 3
Dim tb As StdTab = bar.AddTab("Tab 3")
tb.Tag = panel3
Dim bd As BitmapDrawable
bd.Initialize(LoadBitmap(File.DirAssets, "ic_small.png"))
tb.Icon = bd
In the above code we add three tabs and use the tabs tag property to store a panel in each tab. Later we will use these panels to switch the layout.

When the TabChanged event is raised we clear the current layout and show the new layout.
B4X:
Sub bar_TabChanged(Index As Int, STab As StdTab)
   Activity.RemoveAllViews
   Dim pnl As Panel = STab.Tag
   Dim height As Int
   If 100%y > 100%x Then
     height = 100%y - 48dip 'fix for the additional tabs height
   Else
     height = 100%y
   End If
   Activity.AddView(pnl, 0, 0, 100%x, height)
   If pnl.NumberOfViews = 0 Then
     pnl.LoadLayout(Index)
   End If
End Sub

Note that the attached example uses the Holo.Light theme. This is done with this manifest editor line:
B4X:
SetApplicationAttribute(android:theme, "@android:style/Theme.Holo.Light")

V1.52 is released. Fixes an incompatibility with Android 5.0. Note that the ButtonClicked event will not work on these devices.

You should use Activity_ActionBarHomeClick event instead.
 

Attachments

  • StdActionBarExample.zip
    11 KB · Views: 2,199
  • StdActionBar.zip
    22.9 KB · Views: 1,076
Last edited:

jcesar

Active Member
Licensed User
Longtime User
@jcesar try to add the EditText to a Panel and then add the panel as the custom view. Now try to set the EditText width.

I try, but nothing happens... The panel is not displayed in the actionbar. And if i set the EditText width i get the same NullPointerException error.

I think must be something with layouts... But I dont know if its possible solve with b4a.
 

woniol

Active Member
Licensed User
Longtime User
You should change view size properties after adding it to AB
B4X:
dim edtTeste as EditText
edtTeste.Initialize("")
edtTeste.Hint = "Search !"
edtTeste.TextColor = Colors.White
Dim jo As JavaObject = actionBar
jo = jo.GetField("bar")
jo.RunMethod("setDisplayShowCustomEnabled", ArrayAsObject(true))
jo.RunMethod("setCustomView", ArrayAsObject(edtTeste))

edtTeste.Width = 100dip
 

jcesar

Active Member
Licensed User
Longtime User
You should change view size properties after adding it to AB
B4X:
dim edtTeste as EditText
edtTeste.Initialize("")
edtTeste.Hint = "Search !"
edtTeste.TextColor = Colors.White
Dim jo As JavaObject = actionBar
jo = jo.GetField("bar")
jo.RunMethod("setDisplayShowCustomEnabled", ArrayAsObject(true))
jo.RunMethod("setCustomView", ArrayAsObject(edtTeste))
 
edtTeste.Width = 100dip
Thanks. I will try this...
 

jcesar

Active Member
Licensed User
Longtime User
Hi.

Its possible load a scrollview into the viewpager panels ?

When the device is in landscape mode, many of my views are out of the screen, so i need a vertical scroll to access all the views.
 

Inman

Well-Known Member
Licensed User
Longtime User
Try this:
B4X:
Dim jo As JavaObject = ActionBar1
jo = jo.GetField("bar")
jo.RunMethod("setDisplayShowCustomEnabled", Array As Object(true))
jo.RunMethod("setCustomView", Array As Object(<ViewYouWantToAdd>))

How can I put a Switch View on this Standard Actionbar?
 

woniol

Active Member
Licensed User
Longtime User
View attachment 22721

Relevant code:
B4X:
Sub Globals
  Dim mFragment As MapFragment
  Dim gmap As GoogleMap
  Dim MapPanel As Panel
   Dim bar As StdActionBar
   Dim vp As StdViewPager
End Sub

Sub Activity_Create(FirstTime As Boolean)
  MapPanel.Initialize("")
   bar.Initialize("bar")
   bar.NavigationMode = bar.NAVIGATION_MODE_TABS
   bar.AddTab("Map")
   bar.AddTab("Red panel")
   Dim h As Int = CalculateHeight(True, False)
 
   vp.Initialize("vp", 2, 100%x, h)
   MapPanel.Initialize("")
  Activity.AddView(vp.AsView, 0, 0, 100%x, h)
   vp.Panels(0).AddView(MapPanel,0, 0, 100%x, h)
   vp.Panels(1).Color = Colors.Red
  If mFragment.IsGooglePlayServicesAvailable = False Then
  ToastMessageShow("Google Play services not available.", True)
  Else
  mFragment.Initialize("Map", MapPanel)
  End If
End Sub

Sub CalculateHeight (TabsMode As Boolean, SplitEnabled As Boolean) As Int
   If 100%x >= 480dip Then
     Return 100%y
   Else
     Dim fix As Int
     If TabsMode Then fix = 48dip
     If SplitEnabled Then fix = fix + 48dip
     Return 100%y - fix
   End If
End Sub

Sub VP_PageSelected (Position As Int)
   If bar.SelectedIndex <> Position Then bar.SelectedIndex = Position
End Sub

Sub bar_TabChanged(Index As Int, STab As StdTab)
   If vp.currentPage <> Index Then   vp.ScrollTo(Index, False)
End Sub


Should it work for 3 or more tabs?
When I try to add it to third tab i get this in log:
java.lang.IllegalArgumentException: No view found for id 0x6 for fragment MyMapFragment{42975b68 #0 id=0x6}
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
It should work with any number of tabs:
upload_2014-3-20_15-58-29.png


B4X:
Sub Process_Globals

End Sub


Sub Globals
  Dim mFragment As MapFragment
  Dim gmap As GoogleMap
  Dim MapPanel As Panel
  Dim bar As StdActionBar
  Dim vp As StdViewPager
End Sub

Sub Activity_Create(FirstTime As Boolean)
  MapPanel.Initialize("")
  bar.Initialize("bar")
  bar.NavigationMode = bar.NAVIGATION_MODE_TABS
  bar.AddTab("Map")
  bar.AddTab("Red panel")
  bar.AddTab("Blue panel")
  Dim h As Int = CalculateHeight(True, False)
   
  vp.Initialize("vp", 3, 100%x, h)
  MapPanel.Initialize("")
  Activity.AddView(vp.AsView, 0, 0, 100%x, h)
  vp.Panels(1).AddView(MapPanel,0, 0, 100%x, h)
  vp.Panels(0).Color = Colors.Red
  vp.Panels(2).Color = Colors.Blue
  If mFragment.IsGooglePlayServicesAvailable = False Then
  ToastMessageShow("Google Play services not available.", True)
  Else
  mFragment.Initialize("Map", MapPanel)
  End If
End Sub

Sub CalculateHeight (TabsMode As Boolean, SplitEnabled As Boolean) As Int
  If 100%x >= 480dip Then
  Return 100%y
  Else
  Dim fix As Int
  If TabsMode Then fix = 48dip
  If SplitEnabled Then fix = fix + 48dip
  Return 100%y - fix
  End If
End Sub

Sub VP_PageSelected (Position As Int)
  If bar.SelectedIndex <> Position Then bar.SelectedIndex = Position
End Sub

Sub bar_TabChanged(Index As Int, STab As StdTab)
  If vp.currentPage <> Index Then  vp.ScrollTo(Index, False)
End Sub
 

woniol

Active Member
Licensed User
Longtime User
It should work with any number of tabs:
View attachment 23672

B4X:
Sub Process_Globals

End Sub


Sub Globals
  Dim mFragment As MapFragment
  Dim gmap As GoogleMap
  Dim MapPanel As Panel
  Dim bar As StdActionBar
  Dim vp As StdViewPager
End Sub

Sub Activity_Create(FirstTime As Boolean)
  MapPanel.Initialize("")
  bar.Initialize("bar")
  bar.NavigationMode = bar.NAVIGATION_MODE_TABS
  bar.AddTab("Map")
  bar.AddTab("Red panel")
  bar.AddTab("Blue panel")
  Dim h As Int = CalculateHeight(True, False)
 
  vp.Initialize("vp", 3, 100%x, h)
  MapPanel.Initialize("")
  Activity.AddView(vp.AsView, 0, 0, 100%x, h)
  vp.Panels(1).AddView(MapPanel,0, 0, 100%x, h)
  vp.Panels(0).Color = Colors.Red
  vp.Panels(2).Color = Colors.Blue
  If mFragment.IsGooglePlayServicesAvailable = False Then
  ToastMessageShow("Google Play services not available.", True)
  Else
  mFragment.Initialize("Map", MapPanel)
  End If
End Sub

Sub CalculateHeight (TabsMode As Boolean, SplitEnabled As Boolean) As Int
  If 100%x >= 480dip Then
  Return 100%y
  Else
  Dim fix As Int
  If TabsMode Then fix = 48dip
  If SplitEnabled Then fix = fix + 48dip
  Return 100%y - fix
  End If
End Sub

Sub VP_PageSelected (Position As Int)
  If bar.SelectedIndex <> Position Then bar.SelectedIndex = Position
End Sub

Sub bar_TabChanged(Index As Int, STab As StdTab)
  If vp.currentPage <> Index Then  vp.ScrollTo(Index, False)
End Sub

Ok, but You still add it do the second one:
B4X:
 vp.Panels(1).AddView(MapPanel,0, 0, 100%x, h)
  vp.Panels(0).Color = Colors.Red
  vp.Panels(2).Color = Colors.Blue

please try:
B4X:
 vp.Panels(2).AddView(MapPanel,0, 0, 100%x, h)
  vp.Panels(0).Color = Colors.Red
  vp.Panels(1).Color = Colors.Blue
 
Last edited:

woniol

Active Member
Licensed User
Longtime User
Actually it is in the second panel not the first (the commands order is not important).

I see the error you get if it is in the last page. I'm not sure why it happens. Try it on any of the other panels and it will work.

Looks like it only works with
B4X:
p.Panels(0).AddView(MapPanel,0, 0, 100%x, h)
or
B4X:
p.Panels(1).AddView(MapPanel,0, 0, 100%x, h)

not above it
 

woniol

Active Member
Licensed User
Longtime User
Actually it is in the second panel not the first (the commands order is not important).

I see the error you get if it is in the last page. I'm not sure why it happens. Try it on any of the other panels and it will work.

Looks like it only works with
B4X:
p.Panels(0).AddView(MapPanel,0, 0, 100%x, h)
or
B4X:
p.Panels(1).AddView(MapPanel,0, 0, 100%x, h)

not above it
Good catch.

Add these two lines after you initialize ViewPager:
B4X:
  vp.Initialize("vp", 10, 100%x, h)
  Dim jo As JavaObject = vp
  jo = jo.GetFieldJO("vp").RunMethod("setOffscreenPageLimit", Array As Object(100)) 'the first string is "vp" (not related to the variable)

That's it. Thank You very much for your help.
 

jcesar

Active Member
Licensed User
Longtime User
View attachment 22721

Relevant code:
B4X:
Sub Globals
  Dim mFragment As MapFragment
  Dim gmap As GoogleMap
  Dim MapPanel As Panel
   Dim bar As StdActionBar
   Dim vp As StdViewPager
End Sub

Sub Activity_Create(FirstTime As Boolean)
  MapPanel.Initialize("")
   bar.Initialize("bar")
   bar.NavigationMode = bar.NAVIGATION_MODE_TABS
   bar.AddTab("Map")
   bar.AddTab("Red panel")
   Dim h As Int = CalculateHeight(True, False)
 
   vp.Initialize("vp", 2, 100%x, h)
   MapPanel.Initialize("")
  Activity.AddView(vp.AsView, 0, 0, 100%x, h)
   vp.Panels(0).AddView(MapPanel,0, 0, 100%x, h)
   vp.Panels(1).Color = Colors.Red
  If mFragment.IsGooglePlayServicesAvailable = False Then
  ToastMessageShow("Google Play services not available.", True)
  Else
  mFragment.Initialize("Map", MapPanel)
  End If
End Sub

Sub CalculateHeight (TabsMode As Boolean, SplitEnabled As Boolean) As Int
   If 100%x >= 480dip Then
     Return 100%y
   Else
     Dim fix As Int
     If TabsMode Then fix = 48dip
     If SplitEnabled Then fix = fix + 48dip
     Return 100%y - fix
   End If
End Sub

Sub VP_PageSelected (Position As Int)
   If bar.SelectedIndex <> Position Then bar.SelectedIndex = Position
End Sub

Sub bar_TabChanged(Index As Int, STab As StdTab)
   If vp.currentPage <> Index Then   vp.ScrollTo(Index, False)
End Sub


Hi Erel

The app crashes when i put the map in the last "tab" (vp.panels(2)). This code only works when the mapview is in the first or second tabs.

Maybe i doing something wrong...
 

Inman

Well-Known Member
Licensed User
Longtime User
Try this:
B4X:
Dim jo As JavaObject = ActionBar1
jo = jo.GetField("bar")
jo.RunMethod("setDisplayShowCustomEnabled", Array As Object(true))
jo.RunMethod("setCustomView", Array As Object(<ViewYouWantToAdd>))

In most Android apps (including official Google apps like Gmail), there will be a search button on the actionbar, clicking on which will suddenly display a text box right on the actionbar itself for searching. I understand that we can do it with the above code. But if the user clicks the physical (or on screen) back button on his phone, this text box should disappear, restoring the actionbar to it's original form.

Can we do that in B4A?
 
Top