B4A Library [B4X] [XUI] AS TabMenuAdvanced

A container view controller that manages a multiselection interface, where the selection determines which child view controller to display.

This view was developed and structured from scratch :)

i spend a lot of time in creating views, some views i need by my self, but some views not and to create a high quality view cost a lot of time. If you want to support me, then you can do it here by Paypal or with a coffee. :)

Wo59uAy0swl6vhRC1Qtzzx3iuBG9PXRlW450ZGidq7XLDwkFak.jpeg

(17) mage.png

MiddleButton = True - Designer Property
Examples:
B4X:
AS_TabMenuAdvanced1.GetTab(2).xTab.BadgeValue = 5 'Sets the Badge Value for the 3. Tab to 5
AS_TabMenuAdvanced1.GetTab(3).xTab.Enabled = False 'Disabled the 4. Tab
AS_TabMenuAdvanced1.Refresh 'Commits the changes
Example Projects
ASTabMenuAdvanced
Author: Alexander Stolte
Version: 1.02

  • ASTabMenuAdvanced_BadgeProperties
    • Fields:
      • BackgroundColor As Int
      • Height As Float
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • TextColor As Int
      • TextFont As B4XFont
      • TextPadding As Float
    • Functions:
      • Initialize
        Initializes the fields to their default value.
  • ASTabMenuAdvanced_Tab
    • Fields:
      • BadgeValue As Int
      • Enabled As Boolean
      • IconDisabled As B4XBitmap
      • IconSelected As B4XBitmap
      • IconUnselected As B4XBitmap
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • Tag As Object
      • Text As String
    • Functions:
      • Initialize
        Initializes the fields to their default value.
  • ASTabMenuAdvanced_TabIntern
    • Fields:
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • xBadgeProperties As ASTabMenuAdvanced_BadgeProperties
      • xTab As ASTabMenuAdvanced_Tab
      • xTabProperties As ASTabMenuAdvanced_TabProperties
      • xTabViews As ASTabMenuAdvanced_TabViews
    • Functions:
      • Initialize
        Initializes the fields to their default value.
  • ASTabMenuAdvanced_TabProperties
    • Fields:
      • BackgroundColor As Int
      • DisabledColor As Int
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • SelectedColor As Int
      • TextFont As B4XFont
      • TextIconPadding As Float
      • UnselectedColor As Int
    • Functions:
      • Initialize
        Initializes the fields to their default value.
  • ASTabMenuAdvanced_TabViews
    • Fields:
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • xiv_TabIcon As B4XView
      • xlbl_Badge As B4XView
      • xlbl_TabText As B4XView
      • xpnl_TabBackground As B4XView
    • Functions:
      • Initialize
        Initializes the fields to their default value.
  • AS_TabMenuAdvanced
    • Events:
      • TabClick (Index As Int)
    • Fields:
      • mBase As B4XView
      • Tag As Object
    • Functions:
      • AddTab (Text As String, IconSelected As B4XBitmap, IconUnselected As B4XBitmap) As String
        Text - Pass "" if you dont want Text
        IconSelected - Pass NULL if you dont want a Icon
        IconUnselected - Pass NULL if you dont want a Icon
        If you want to change TabProperties then call this before you add the tab
        <code>AS_TabMenuAdvanced1.TabProperties.TextColor = xui.Color_White</code>
      • AddTabAdvanced (xTab As ASTabMenuAdvanced_Tab, xTabProperties As ASTabMenuAdvanced_TabProperties) As String
        Example:
        <code>
        Dim xTab As ASTabMenuAdvanced_Tab = AS_TabMenuAdvanced1.CreateASTabMenuAdvanced_Tab("Test Item",Null,Null)
        Dim xTabProperties As ASTabMenuAdvanced_TabProperties = AS_TabMenuAdvanced1.CreateASTabMenuAdvanced_TabProperties(xui.CreateDefaultFont(15),xui.Color_ARGB(255,32, 33, 37),xui.Color_ARGB(255,45, 136, 121),xui.Color_ARGB(255,255,255,255),xui.Color_ARGB(255,60, 64, 67),0)
        AS_TabMenuAdvanced1.AddTabAdvanced(xTab,xTabProperties)</code>
      • ChangeColorBasedOnAlphaLevel (bmp As B4XBitmap, NewColor As Int) As B4XBitmap
      • Class_Globals As String
      • CreateASTabMenuAdvanced_BadgeProperties (TextColor As Int, TextFont As B4XFont, Height As Float, TextPadding As Float, BackgroundColor As Int) As ASTabMenuAdvanced_BadgeProperties
      • CreateASTabMenuAdvanced_Tab (Text As String, IconSelected As B4XBitmap, IconUnselected As B4XBitmap) As ASTabMenuAdvanced_Tab
      • CreateASTabMenuAdvanced_TabIntern (xTab As ASTabMenuAdvanced_Tab, xTabProperties As ASTabMenuAdvanced_TabProperties, xBadgeProperties As ASTabMenuAdvanced_BadgeProperties, xTabViews As ASTabMenuAdvanced_TabViews) As ASTabMenuAdvanced_TabIntern
      • CreateASTabMenuAdvanced_TabProperties (TextFont As B4XFont, BackgroundColor As Int, SelectedColor As Int, UnselectedColor As Int, DisabledColor As Int, TextIconPadding As Float) As ASTabMenuAdvanced_TabProperties
      • CreateASTabMenuAdvanced_TabViews (xpnl_Tab As B4XView, xlbl_TabText As B4XView, xiv_TabIcon As B4XView, xlbl_Badge As B4XView) As ASTabMenuAdvanced_TabViews
      • CreateImageView (EventName As String) As B4XView
      • CreateLabel (EventName As String) As B4XView
      • DesignerCreateView (Base As Object, Lbl As Label, Props As Map) As String
        Base type must be Object
      • FontToBitmap (text As String, IsMaterialIcons As Boolean, FontSize As Float, color As Int) As B4XBitmap
      • getIndex As Int
      • GetTab (Index As Int) As ASTabMenuAdvanced_TabIntern
        Example:
        <code>
        AS_TabMenuAdvanced1.GetTab(0).xTabProperties.SelectedColor = xui.Color_Magenta
        AS_TabMenuAdvanced1.Refresh</code>
      • getTabProperties As ASTabMenuAdvanced_TabProperties
      • GetTabs As List
        Example:
        <code>
        For Each TabIntern As ASTabMenuAdvanced_TabIntern In AS_TabMenuAdvanced1.GetTabs
        Log(TabIntern.xTab.Text)
        Next</code>
      • Initialize (Callback As Object, EventName As String) As String
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • Refresh As String
      • RemoveTabAt (Index As Int) As String
        Removes a tab
        <code>
        AS_TabMenuAdvanced1.RemoveTabAt(2)
        AS_TabMenuAdvanced1.Refresh</code>
      • setIndex (Index As Int) As String
    • Properties:
      • Index As Int
      • TabProperties As ASTabMenuAdvanced_TabProperties [read only]
Changelog
  • 1.00
    • Release
  • 1.01
    • xBadge renamed to xBadgeProperties
  • 1.02
    • Add GetTabs - Gets a list of tab properties of type ASTabMenuAdvanced_TabIntern
    • Add RemoveTabAt - Removes a tab
    • Add Tag Property to Type ASTabMenuAdvanced_Tab
    • Add new Type ASTabMenuAdvanced_TabViews - contains the control elements of a tab
  • 1.03
    • Add LeftPadding to ASTabMenuAdvanced_BadgeProperties - You can move the badge to left or right with this property
    • Add get BadgeProperties - here you can set the global Badge Properties
  • 1.04
    • The TabClick Event is now always triggered, even if the tab is already selected
    • The BadgeValue Data Type from Type ASTabMenuAdvanced_Tab is now String
  • 1.05
    • Add get and set CornerRadius
    • Add new Type ASTabMenuAdvanced_IndicatorProperties
    • Add Designer Property Indicator - If True the Indicator is visible
      • Default: False
    • BugFixes
  • 1.06
    • Add Designer Property MiddleButton - You can now show a middle button
      • Default: False
      • Limitation: Only an even number of tabs may be present 2,4,6,8,10...
    • Add Event MiddleButtonClick
    • Add Type ASTabMenuAdvanced_MiddleButtonProperties
      • CustomWidth
        • Default: 0
    • Add Designer Property BadgeWithoutText - If True then the badges have no text
      • Default: False
  • 1.07
    • Add Visible to Type ASTabMenuAdvanced_MiddleButtonProperties - If False then the middle button is not visible, but the space is still kept free
  • 1.08
    • Add Designer Property ColorIcons - If false then remains the color of the icon
      • Default: True
  • 1.09
    • Add Event CustomDrawTab - This ensures that whenever a tab is refreshed, your custom code is also applied
  • 1.10
    • BugFix
  • 1.11
    • Badge optimizations
  • 1.12
    • Add Clear - Clears all tabs
  • 1.13
    • BugFix - the badge was not round when the width was smaller than the height
    • Add BadgeValue - Sets the badge value without having to call refresh
    • set Index no longer needs a "refresh" to be changed
  • 1.14
    • BugFix on .Clear
  • 1.15
    • BugFix on MiddleButtonProperties.CustomWidth
  • 1.16
    • BugFixes
Have Fun :)
 

Attachments

  • AS TabMenuAdvanced Example.zip
    449.1 KB · Views: 1,364
  • AS_TabMenuAdvanced.b4xlib
    7.6 KB · Views: 110
Last edited:

fbritop

Active Member
Licensed User
Longtime User
This looks great, is there, or how can a tab width be setted in order to make the tab only with a single line, but the width achieved for every tab, calculating the width on our side with b4xRect?

Thanks!
 

fbritop

Active Member
Licensed User
Longtime User
Sorry thats not possible. That's not what the view is made for. If you want a view that can do that, then have a look at the AS_SegmentedTab
Thanks... This could be an update. A method to remove all views. I do it manually right now

B4X:
                If xFlowTab.GetTabs.Size>0 Then
                    For i=xFlowTab.GetTabs.Size-1 To 0 Step -1
                        xFlowTab.RemoveTabAt(i)
                    Next
                End If
                xFlowTab.Refresh
 

Alexander Stolte

Expert
Licensed User
Longtime User
Update
  • 1.13
    • BugFix - the badge was not round when the width was smaller than the height
    • Add BadgeValue - Sets the badge value without having to call refresh
    • set Index no longer needs a "refresh" to be changed
 
Last edited:

Sergio Haurat

Active Member
Licensed User
Longtime User
Hello @Alexander Stolte, I'm trying to do something that I'm not sure if the [B4X] [XUI] AS TabMenuAdvanced library is designed for. Basically, I want to add some icons; if I select the first one, it clears the current configuration and displays others. Here's the code that builds the menu.
Sub makeMenu:
Private Sub makeMenu(strView As String)
    If btnTabMenu.GetTabs.Size > 0 Then
        btnTabMenu.Clear
    End If
    Select Case strView
        Case "main"
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_user_db.png"), xui.LoadBitmap(File.DirAssets,"icon_user_db.png"))
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_chart.png"), xui.LoadBitmap(File.DirAssets, "icon_chart.png"))
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_padlock.png"), xui.LoadBitmap(File.DirAssets, "icon_padlock.png"))
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_social.png"), xui.LoadBitmap(File.DirAssets,"icon_social.png"))
            btnTabMenu.GetTab(0).xTab.Tag = "userDB"
            btnTabMenu.GetTab(1).xTab.Tag = "chart"
            btnTabMenu.GetTab(2).xTab.Tag = "padLock"
            btnTabMenu.GetTab(3).xTab.Tag = "social"
            If Not(Main.blnIsDBConnected) Then
                btnTabMenu.GetTab(0).xTab.Enabled = False
                btnTabMenu.GetTab(1).xTab.Enabled = False
                btnTabMenu.GetTab(2).xTab.Enabled = False
            End If
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_exit.png"), xui.LoadBitmap(File.DirAssets,"icon_exit.png"))
            btnTabMenu.GetTab(4).xTab.Tag = "exit"
        Case "userDB"
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_find.png"), xui.LoadBitmap(File.DirAssets,"icon_find.png"))
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_edit.png"), xui.LoadBitmap(File.DirAssets, "icon_edit.png"))
            btnTabMenu.AddTab("", xui.LoadBitmap(File.DirAssets, "icon_previus.png"), xui.LoadBitmap(File.DirAssets,"icon_previus.png"))
            btnTabMenu.GetTab(0).xTab.Tag = "findTeam"
            btnTabMenu.GetTab(1).xTab.Tag = "editUser"
            btnTabMenu.GetTab(2).xTab.Tag = "back"
    End Select
    btnTabMenu.Refresh
End Sub
Sub btnTabMenu_TabClick:
Private Sub btnTabMenu_TabClick (Index As Int)
    Select Case btnTabMenu.GetTab(Index).xTab.Tag
        Case "userDB"
            makeMenu("userDB")
        Case "back"
            makeMenu("main")
        Case "exit"
            #if B4a
            Msgbox2Async(Main.loc.Localize("exit_app"), Main.loc.Localize("app_name"), Main.loc.Localize("yes"), "", Main.loc.Localize("cancel"), Null, False)
            Wait For MsgBox_Result (Result As Int)
            If Result = DialogResponse.POSITIVE Then
                Root.RemoveAllViews
                B4XPages.ClosePage(Me)
                ExitApplication
            End If
            #else if B4i
            Msgbox2("Msg", Main.loc.Localize("exit_app"), Main.loc.Localize("app_name"), Array (Main.loc.Localize("yes"), Main.loc.Localize("cancel")))
            Wait For Msg_Click (ButtonText As String)
            If ButtonText = Main.loc.Localize("yes") Then
                Root.RemoveAllViews
                B4XPages.ClosePage(Me)
            End If
      #End If
    End Select
End Sub

On the first run, it doesn't generate any issues. However, when I select the icon with the Tag userDB, it shows the following error.

Error occurred on line: 386 (AS_TabMenuAdvanced)
java.lang.RuntimeException: Object should first be initialized (View).
Did you forget to call Activity.LoadLayout?
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
at anywheresoftware.b4a.objects.B4XViewWrapper.GetView(B4XViewWrapper.java:335)
at ar.com.sysprofile.psahb.as_tabmenuadvanced._clear(as_tabmenuadvanced.java:943)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:262)
at ar.com.sysprofile.psahb.b4xmainpage._makemenu(b4xmainpage.java:708)
at ar.com.sysprofile.psahb.b4xmainpage$ResumableSub_btnTabMenu_TabClick.resume(b4xmainpage.java:912)
at ar.com.sysprofile.psahb.b4xmainpage._btntabmenu_tabclick(b4xmainpage.java:838)
at java.lang.reflect.Method.invoke(Native Method)

Thank you for your response and for your great work.
 

Sergio Haurat

Active Member
Licensed User
Longtime User
Can you please show me this in an example project? Thank you
I'll prepare it in minutes and attach it.

A possible bug in version 1.13 that doesn't require a refresh is that when btnTabMenu.Index = -1 is used to prevent it from being selected by default, it now generates the following error.

Error occurred on line: 523 (AS_TabMenuAdvanced)
java.lang.RuntimeException: Object should first be initialized (View).
Did you forget to call Activity.LoadLayout?
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:67)
at anywheresoftware.b4a.objects.B4XViewWrapper.GetView(B4XViewWrapper.java:335)
at ar.com.sysprofile.psahb.as_tabmenuadvanced._setindex(as_tabmenuadvanced.java:216)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
at anywheresoftware.b4a.BA$2.run(BA.java:395)
at android.os.Handler.handleCallback(Handler.java:984)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loopOnce(Looper.java:238)
at android.os.Looper.loop(Looper.java:357)
at android.app.ActivityThread.main(ActivityThread.java:8118)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:957)
 

Alexander Stolte

Expert
Licensed User
Longtime User
A possible bug in version 1.13 that doesn't require a refresh is that when btnTabMenu.Index = -1 is used to prevent it from being selected by default, it now generates the following error.
This is not a bug, because there is a property for this:
Just uncheck the "First Tab Selected" property in the designer
1705345708329.png
 

Sergio Haurat

Active Member
Licensed User
Longtime User
This is not a bug, because there is a property for this:
Just uncheck the "First Tab Selected" property in the designer
View attachment 149738
It works perfectly. I hadn't noticed the property in the designer. Now I'm removing .Index - 1 from the entire code.

I'm attaching the example project you requested in this post
 

Attachments

  • AS TabMenuAdvanced.zip
    134.9 KB · Views: 45

fbritop

Active Member
Licensed User
Longtime User
Hi,
How can we "Ignore" TabClick?

I have an App that takes a little bit to load the results, but if the user switchs tabs, the event gets trigger. I have overcome this by having a "Working" Flag indicator, it acomplishes the job, but the tab indicator switches anyway, causing a little confusion. Is there any "IgnoreEvents" option?

THanks
FBP
 

fbritop

Active Member
Licensed User
Longtime User
Hi,
How can we "Ignore" TabClick?

I have an App that takes a little bit to load the results, but if the user switchs tabs, the event gets trigger. I have overcome this by having a "Working" Flag indicator, it acomplishes the job, but the tab indicator switches anyway, causing a little confusion. Is there any "IgnoreEvents" option?

THanks
FBP
Took the freedom to modify it, maybe could be of help for a new version

Line 114
B4X:
Private m_IgnoreEvents as Boolean=False

Line 404
B4X:
Public Sub setIgnoreEvents(Ignore as Boolean)
    m_IgnoreEvents=Ignore
End Sub

Line 574
B4X:
If isUserTap and Not(m_IgnoreEvents) Then


Line 644
B4X:
If isUserTap and Not(m_IgnoreEvents) Then TabClickEvent(m_Index)
 

Alexander Stolte

Expert
Licensed User
Longtime User
I have an App that takes a little bit to load the results, but if the user switchs tabs, the event gets trigger. I have overcome this by having a "Working" Flag indicator, it acomplishes the job, but the tab indicator switches anyway, causing a little confusion. Is there any "IgnoreEvents" option?
Even with an ignore event, the user can switch tabs, only without an event, which also causes confusion.

The library has a much better function than an ignore event.
Disable the tabs and activate it again when you have finished loading.
B4X:
    For Each TabIntern As ASTabMenuAdvanced_TabIntern In AS_TabMenuAdvanced1.GetTabs
        TabIntern.xTab.Enabled = False
    Next
    AS_TabMenuAdvanced1.Refresh

Please always open a new thread if you have any questions, thank you very much, have a good start to the week.
 
Top