Android Tutorial ActionBar / Sliding Pages tutorial

A simpler and better looking solution is now available: https://www.b4x.com/android/forum/threads/tabstripviewpager-better-viewpager.63975/

StdActionBar library allows you to create layouts that use the action bar as a navigation interface.
Note that StdActionBar requires Android 4+.

In this tutorial we will create this layout:

upload_2014-1-19_15-27-46.png
upload_2014-1-19_15-28-3.png


The user can switch pages with a swipe gesture.

StdViewPager holds several panels and supports the swipe gesture.

Using StdViewPager is quite simple:

1. Initialize it and set the number of pages and their size.
2. Add it to its parent.
3. Create the internal pages layouts.

B4X:
Dim height As Int = CalculateHeight(True, True)
vp.Initialize("vp", 3, 100%x, height) 'vp is a StdViewPager object
Activity.AddView(vp.AsView, 0, 0, 100%x, height)
'load the pages layouts
vp.Panels(0).LoadLayout("0")
vp.Panels(1).LoadLayout("1")
vp.Panels(2).LoadLayout("2")

The next step is to add the ActionBar tabs:
B4X:
bar.Initialize("bar")
bar.NavigationMode = bar.NAVIGATION_MODE_TABS
bar.AddTab("Tab 1")
bar.AddTab("Tab 2")
bar.AddTab("Tab 3")

We need to synchronize the selected tab and the selected page:
B4X:
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

CalculateHeight (TabsMode As Boolean, SplitEnabled As Boolean) is a helper sub that calculates the pages height based on the two features.
As you can see in the first screenshot, the split mode is enabled in this case. In split mode the action bar menu items appear at the bottom in portrait mode (phones only). This is set by adding the following line to the manifest editor:
B4X:
SetApplicationAttribute(android:uiOptions, "splitActionBarWhenNarrow")

The project is attached. Note that it requires StdActionBar v1.50+.

Tips:

- You can show the "up indicator" by setting ShowUpIndicator to True:

SS-2014-01-19_15.41.50.png


You can then handle the ButtonClicked event and use it to navigate to the "parent" activity.

- The holo.light theme is used in this project. It is done with this manifest line:
B4X:
SetApplicationAttribute(android:theme, "@android:style/Theme.Holo.Light")
 

Attachments

  • ActionBar.zip
    14.1 KB · Views: 7,383
Last edited:

zombee81

Member
Licensed User
Longtime User
Erel, thanks for this library, its fantastic. An idea for a future one, a ActionBar library that uses the sherlock actionbar so that it will be compatible with all versions of android down to 2.1.
 

imgsimonebiliato

Well-Known Member
Licensed User
Longtime User
Hello,
trying to use this library i get in the manifestor, this error:


B4X:
AndroidManifest.xml:15: error: No resource identifier found for attribute 'uiOptions' in package 'android'
AndroidManifest.xml:15: error: Error: No resource found that matches the given name (at 'theme' with value '@android:style/Theme.Holo.Light').

Please help
 

M. Giray Ozkan

Member
Licensed User
Longtime User
Dear Erel,

I have trouble adding menu items to actionbar. I'm using addmenuItem3 but 3 dot menu icon doesn't appear on top right corner. please help. Thank you.

B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="17"/>
<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, "@style/Theme.MyCustomTheme")
SetActivityAttribute(addReminderActivity, android:windowSoftInputMode, adjustResize|stateHidden)
AddPermission(android.permission.VIBRATE)


B4X:
Activity.AddMenuItem3("", "mnuUser", LoadBitmap(File.DirAssets, "ic_action_user.png"), True)
      
    Activity.AddMenuItem3("Menu Option 1", "mnuOpt1",Null,False)
    Activity.AddMenuItem3("Menu Option 2", "mnuOpt2",Null,False)
    Activity.AddMenuItem3("Menu Option 3", "mnuOpt3",Null,False)
    Activity.AddMenuItem3("Menu Option 4", "mnuOpt4",Null,False)


by the way, I'm using LG-G2 phone with Android 4.2.2
 
Last edited:

Roger C

Active Member
Licensed User
Longtime User
Looks very interesting!!!

And here comes a stupid question...
I'm working on an app with many layouts which now are accessed through buttons on the startpage.
If I would implement this instead where I load the layouts in panels, would the layouts still be connected to the old activitymodule where I loaded the layouts before? So I don't have to rewrite anything and place it all in Main where this code goes?
It's just another way of showing the different layouts?

And another...
Would it be possible to load images in the tabs instead of text? If I have 5 tabs, four of them are visible and then there isn't much space for text. 'Settings' is cropped and I have to write 'Set.' instead. Doesn't look so good. :)
 

Roger C

Active Member
Licensed User
Longtime User
Been trying to integrate this in my current app but I can't get it working.

In my old version, pressing a button on startscreen opened another Activity (Act2), displayed that layout and run some code to update information on the screen.

When placing the layout for Act2 in panel 1 (panel 0 = startscreen) and sliding/pressing tab to panel 1, it shows the layout but the buttons don't work and they are not updated with new information.
So I placed a check in 'Sub VP_PageSelected' to check for panel 1 and then run the start code by CallSub from Act2 but nothing happens.

How can I implement this in an existing app? And how can I update the information in the layout in the panel I slide to? Do I have to update all layouts on all panels when I create them? Then it don't work for me since I use dynamic data that could change between panels and have to be updated when it comes into view.

How do I handle the press of buttons on the layouts? Do all code have to be in Main and catch the button pressed?

Am I missing something here?
 

netchicken

Active Member
Licensed User
Longtime User
Erel I think I have the same question as Roger above.
I have 4 layouts that are at present opened by 4 activities using Buttons. Each layout is loaded with data from the class in the Activity.

Is there a way to fill each layout with the data (its only 1 line of data) with this system? Or can I only use 4 panels and one Activity?
 

netchicken

Active Member
Licensed User
Longtime User
I seem to have found an answer.
By adding the fields (Labels) to the same activity that holds the sliding pages code, it seems to fill the labels in the layouts with the correct data.
 

Roger C

Active Member
Licensed User
Longtime User
Netchicken,

I've made a solution with one Activity and classes loading Layouts and this works fine for me so far. Supplied here are the framework of this setup. I've been searching a lot for a working solution and thought I'd share this, might help others in the same situation.

The Activity has an Actionbar in top and another in bottom (which works as a statusbar for me).
Changes in the Actionbars can be done by calling a sub in Main like:
B4X:
CallSub(Main,"ActivityLowerBar")
or in the top bar
B4X:
CallSub(Main,"ActivityTopBar")
I use KeyValueStore to send variables between classes and activity, a bit slower than global variables but safer if the app shuts down.

I also have slidingmenues (http://www.b4x.com/android/forum/threads/jfeinstein10-slidingmenu-library.36482/) to the left, with buttons for selecting function and to the right with a ScrollView that can be used for anything you want.

The menubuttons loads the classes like this:
B4X:
sm.HideMenus
Activity.RemoveAllViews
lClsHistory.Initialize(Me, Activity, 2)
Then the class loads the Layouts and each class will handle the events from that layout.
This means you have the Activity common for the project and just change the visible layouts by initializing the classes.

I've also implemented a Multilanguage function based on this http://www.b4x.com/android/forum/threads/ahlocale-library.7561/.
Texts are used in this way:
B4X:
btnKund.text=trans.GetText("Customer")
I only have Swedish at the moment as complement to English (the english is the text Customer above) and the Swedish is looked up in a text file in the folder /Files.

Noticed that the Backbutton on the device don't work but thats easy to solve for you...
The sliding doesn't work so good on the emulator but it does on a real device.

Notice that you will need some libraries...
Since this frame is taken from my complete app there are a lot of libs and I really don't know which are used for only the frame to work... But try and add them one at a time when you get error...
These are the libs used: AHLocale, Core, DateUtils, Dialogs, HTTP, JavaObject, JSON, Net, Phone, RandomAccessFile, Reflection, ScrollView2D, SlidingMenuWrapper, SQL, StdActionbar, StringFunctions, StringUtils, TabHostExtras, XmlSax.
 

Attachments

  • Frame.zip
    48.7 KB · Views: 1,730
Last edited:

luke2012

Well-Known Member
Licensed User
Longtime User
@Erel
Very good work!
Only a question : In the tutorial's screenshots I don't see the action overflow. Is it supported ?
 
Top