Android Tutorial [B4X] B4XPages - Cross platform and simple framework for managing multiple pages

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
B4XPages is a library that serves two purposes:

1. Make it simple to develop B4A apps by solving almost all of the challenges involved with Android complex activities life cycle.
B4XPages makes B4A behave more similar to B4J and B4i where the new "B4XPage" element is a regular object that is never paused, never destroyed, can be accessed from anywhere and easy to work with.
2. Provide a cross platform layer above the navigation related APIs.

Before we start:

1. You are not forced to use B4XPages. All the current features behave exactly as before.
2. B4XPages is currently in beta version. The API is not final, things might change.
3. It does have some limitations. One notable limitation is that in B4A, the activity that holds all the pages should be locked to a single orientation.
4. It is supported by the latest versions of B4J, B4i and B4A.


(video from B4i)

What exactly does it solve?

Here: https://www.b4x.com/android/forum/threads/b4x-b4xpages-what-exactly-does-it-solve.119078/

What is a B4XPage?

It differs between the three platforms:
B4J - Form
B4i - Page in a single NavBarController
B4A - Panel in a single activity.

Lets start:

1. There is some template code that needs to be added to the main module. You can use the attached cross platform template, even if you are only interested in a single platform, or you can write:
B4X:
Dim pm As B4XPageManager
Hover over B4XPageManager and select copy.

2. Each page is implemented in its own class. The class template is very simple and looks like this:
B4X:
Sub Class_Globals
    Private Root As B4XView 'ignore
    Private xui As XUI 'ignore
End Sub

'You can add more parameters here.
Public Sub Initialize

End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    'load the layout to Root

End Sub
3. There must be one class named B4XMainPage. This page will usually be the first one to be displayed.
4. B4XPage_Created event is raised when a page is created, this will happen before it is displayed for the first time. Note that pages are never destroyed.
This is the place to load the layout.
5. The way to access the various B4XPages related features is with B4XPages, an internal code module.
6. Each page is identified with a case insensitive string id. The main page id is "MainPage".
7. Example of adding a page:
B4X:
Dim Page2 As B4XPage2
Page2.Initialize
B4XPages.AddPage("Page 2", Page2)
8. Example of showing a page:
B4X:
B4XPages.ShowPage("Page 3")
9. As the pages instances are regular objects there are many simple ways to access them. One simple way is with B4XPages.GetPage:
B4X:
Page3 = B4XPages.GetPage("Page 3")
Page3.Button1.Text = "abc"
10. Several methods expect a B4XPage object. In most cases, you will pass Me:
B4X:
B4XPages.SetTitle(Me, "Draw Something")
11. You can see the list of events by writing: Sub + space + tab and choosing B4XPageManager. The event name is always B4XPage.
12. The pages context will not be paused or destroyed, until the process itself is killed.
13. There is a field named B4XPages.B4XGlobalContext. The use case behind it is with a class instance that is initialized in Service_Create of the starter service. This can be a good place to implement tasks that can also run in the background.
14. There are many more details but for now you are ready to start playing with it. See the attached example.


Updates:
v1.03 - Adds support for menu items. This version is included in B4A v9.90 and B4J v8.31

Latest templates versions (included in CrossPlatformProject_Template.zip):
B4A-1.0
B4J-1.0
B4i-1.0

B4XPages is an internal library in B4A and B4J. It will be internal library in the next version of B4i.

B4XPages related discussions: https://www.b4x.com/android/forum/pages/results/?query=b4xpages
Make sure to use B4A v9.90+, B4J v8.31+ or B4i v6.50+ (you will need to add the library to B4i).
 

Attachments

Last edited:

Erel

Administrator
Staff member
Licensed User
B4XPages v1.02 released. The action bar, in B4A, shows an "up" indicator when their are pages behind the current one.



Note that in the example the switch from the login page to the second page is done with:
B4X:
B4XPages.ShowPageAndRemovePreviousPages("MainPage")
This causes the previous pages on the stack to be removed. It means that we don't want the user to click on the back key and return to the login page.
 

Erel

Administrator
Staff member
Licensed User
In B4A and B4J you can handle the CloseRequest event and cancel the request if needed.

Example:
B4X:
'Return True to close, False to cancel
Private Sub B4XPage_CloseRequest As ResumableSub
    Dim sf As Object = xui.Msgbox2Async("Close?", "Title", "Yes", "Cancel", "No", Null)
    Wait For (sf) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Return True
    End If
    Return False
End Sub
 
Last edited:

Erel

Administrator
Staff member
Licensed User
V1.03 released with support for menus. Note that the B4A template was also updated.

Menus in B4J and B4i are added with the visual designer. In B4J with the MenuBar control and the json string that defines the items. In B4i with the Top Right Buttons in the Main control properties.

In B4J, the MenuBar_Action event will be raised by default. It is recommended to add this sub, which delegates the event to the B4XPage_MenuClick event:
B4X:
#if B4J
'Delegate the native menu action to B4XPage_MenuClick.
Sub MenuBar1_Action
    Dim mi As MenuItem = Sender
    Dim t As String
    If mi.Tag = Null Then t = mi.Text.Replace("_", "") Else t = mi.Tag
    B4XPage_MenuClick(t)
End Sub
#End If
Change the event name if needed.

In B4A it is done in B4XPage_Created using the new B4XPages.AddMenuItem:
B4X:
B4XPages.AddMenuItem(Me, "Example")
The tag property is set by default to the title. AddMenuItem returns a B4AMenuItem object that you can further modify:
B4X:
Dim mi As B4AMenuItem = B4XPages.AddMenuItem(Me, "Main 2")
mi.AddToBar = True
mi.Bitmap = xui.LoadBitmapResize(File.DirAssets, "image.png", 64dip, 64dip, True)
See the updated ThreePages example. There is a menu item in B4XPage3.
 

Erel

Administrator
Staff member
Licensed User
B4XPages Events

  • B4XPage_Created - Called once when the page is created. This will happen before the page becomes visible or after a call to B4XPages.AddPageAndCreate.
  • B4XPage_Appear - Called whenever the page becomes visible.
  • B4XPage_Disappear - Called whenever a visible page disappear.
  • B4XPage_Background - Called when the app is moved to the background. This event will be raised in all pages that implement this sub, not just the top event. This is a good place to save anything that needs to be save as the process might be killed later. Note that in B4J it is raised when the last page is closed.
  • B4XPage_Foreground - Called when the app moved to the foreground.
  • B4XPage_Resize (B4J / B4i) - Called when the page is resized.
  • B4XPage_CloseRequest (B4J / B4A) - In B4A it is called when the user clicks on the back key or on the up indicator. In B4J it is called when the user clicks on the close button. See post #4 for more information.
  • B4XPage_MenuClick - Called when a menu item item or BarButton in B4i is clicked. See post #5 for more information.
  • B4XPage_KeyboardStateChanged (B4i) - Called when the keyboard state changes.
  • B4XPage_IconifiedChanged (B4J) - Called when a page is minimized or restored.
  • B4XPage_PermissionResult (B4A) - Raised after a call to rp.CheckAndRequest.
 

Erel

Administrator
Staff member
Licensed User
Handling the IME_HeightChanged event in B4A, to handle keyboard state changes:

Add to Main module:
B4X:
Sub Globals
    Private ime As IME
End Sub

Sub Activity_Create(FirstTime As Boolean)
    ime.Initialize("IME")
    ime.AddHeightChangedEvent
    Dim pm As B4XPagesManager
    pm.Initialize(Activity)
End Sub

Sub IME_HeightChanged (NewHeight As Int, OldHeight As Int)
    B4XPages.GetManager.RaiseEvent(B4XPages.GetManager.GetTopPage, "IME_HeightChanged", Array(NewHeight, OldHeight))
End Sub
Now implement the IME_HeightChanged (NewHeight As Int, OldHeight As Int) event in any page you need.

Don't forget to add to the manifest editor:
B4X:
SetActivityAttribute(main, android:windowSoftInputMode, adjustResize|stateHidden)
 
Last edited:

Erel

Administrator
Staff member
Licensed User
B4XMainPage is always created when the app starts. The first page that is created is also displayed. This means that by default the main page will be displayed when the app starts.

You can however, add a page in B4XMainPage Initialize sub. This will cause the page to be the first to be displayed. You can later show the main page if you like with:
B4X:
B4XPages.ShowPage("MainPage")
 

Erel

Administrator
Staff member
Licensed User
B4XPage template that handles iOS safe area:
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    #if B4A or B4J
    Root = Root1
    #else if B4i
    Root = xui.CreatePanel("")
    Root1.Color = xui.Color_White
    Root1.AddView(Root, 0, 0, Root1.Width, Root1.Height)
    #end if
    'load the layout
    Root.LoadLayout("Center")
End Sub

Private Sub B4XPage_Resize (Width As Float, Height As Float)
    #if B4i
    Dim r As Rect = B4XPages.GetNativeParent(Me).SafeAreaInsets
    Root.SetLayoutAnimated(0, r.Left, r.Top, Width - r.Right - r.Left, Height - r.Bottom - r.Top)
    #end if
End Sub
 
Status
Not open for further replies.
Top