B4A Class [B4X] [XUI] AS BottomMenu

A better menu, can you find here
Screenshot_20200224-203427__01.jpg

A complete New and better Version of this View is available now. (V2)

I'm very happy to share my first customview with the community.
I develop Cross Platform Apps, it was too much code and too much effort to assemble my own bottom menu from many views. So I decided to build a class that I just need to add one view in the designer with less work. ;)

-You have many options to customize the menu.
-easy to use
-compatible with B4A,B4I and B4J
-you can hide the middle Button
-4 Tabs or 2 Tabs

It is optimized for B4A and B4I, on B4J it is still a little buggy, but i dont need it for B4J.

Android, B4J ,2Tabs
4tabs android.PNG asbottommenu b4j.PNG 2tabs android.PNG
since Version 1.2 it is possible to replace the big middle button with further page (page5) more information about it, in #13
newmiddle button.PNG


IOS Android
4tabs ios gif.gif
4tabs android gif.gif


Since Version 1.6 it is possible to add Text:
Screenshot_20180912-131955__01.jpg


AS Bottom Menu

Author: Alexander Stolte
Version: 1.6

  • ASBottomMenu
    • Events:
      • MiddleButtonClick
      • MiddleButtonLongClick
      • Page1Click
      • Page2Click
      • Page3Click
      • Page4Click
      • Page5Click
    • Functions:
      • ChangeMiddleButtonSize (size As Double, BorderWidth As Double) As String
        Standard Value are the height of the view/1.2. Standard BorderWidth are 3dip.
      • Class_Globals As String
      • DesignerCreateView (Base As Object, Lbl As Label, Props As Map) As String
      • EnableBadget1 (Enable As Boolean) As String
        If True, the Badget is Visible, if not, the Badget is hidden.
      • EnableBadget2 (Enable As Boolean) As String
        If True, the Badget is Visible, if not, the Badget is hidden.
      • EnableBadget3 (Enable As Boolean) As String
        If True, the Badget is Visible, if not, the Badget is hidden.
      • EnableBadget4 (Enable As Boolean) As String
        If True, the Badget is Visible, if not, the Badget is hidden.
      • EnableBadget5 (Enable As Boolean) As String
        If True, the Badget is Visible, if not, the Badget is hidden.
      • EnableSelectedPageColor (enable As Boolean) As String
        If True then the Icon will change the Color on the current Page.
      • EnableText (Enable As Boolean) As String
      • GetBase As B4XView
      • HideBadgetValue (badget As Int, Hide As Boolean) As String
        If True only the badget color is display without value inside. badget as int = 1-4 allowed.
      • Initialize (CallBack As Object, EventName As String) As String
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • SetBadgetColor1 (color As Int) As String
        Set the Background Color of the 1. Badget
      • SetBadgetColor2 (color As Int) As String
        Set the Background Color of the 2. Badget
      • SetBadgetColor3 (color As Int) As String
        Set the Background Color of the 3. Badget
      • SetBadgetColor4 (color As Int) As String
        Set the Background Color of the 4. Badget
      • SetBadgetColor5 (color As Int) As String
        Set the Background Color of the 5. Badget
      • SetBadgetValue1 (value As Int) As String
        Set on the 1. Badge the Value. Bigger then 9, a "9+" is Displayed
      • SetBadgetValue2 (value As Int) As String
        Set on the 2. Badge the Value. Bigger then 9, a "9+" is Displayed
      • SetBadgetValue3 (value As Int) As String
        Set on the 3. Badge the Value. Bigger then 9, a "9+" is Displayed
      • SetBadgetValue4 (value As Int) As String
        Set on the 4. Badge the Value. Bigger then 9, a "9+" is Displayed
      • SetBadgetValue5 (value As Int) As String
        Set on the 5. Badge the Value. Bigger then 9, a "9+" is Displayed
      • SetCurrentPage (page As Int) As String
        Set the current Page 1-4
      • SetIcon1 (icon As B4XBitmap) As String
      • SetIcon2 (icon As B4XBitmap) As String
      • SetIcon3 (icon As B4XBitmap) As String
      • SetIcon4 (icon As B4XBitmap) As String
      • SetIcon5 (icon As B4XBitmap) As String
      • SetMenuBackgroundColor (color As Int) As String
        Set the Background color behind the Buttons.
      • SetMiddleButtonBackgroundColor (color As Int) As String
        Set the Middle Button Background Color
      • SetMiddleButtonIcon (icon As B4XBitmap) As String
        Set the Icon of the Middle Button
      • SetMiddleButtonVisible (Visble As Boolean) As String
      • SetPageClickColor (color As Int) As String
        The Color of Halo Effect during Page Click.
      • SetPartingLineColor (color As Int) As String
        Set the Color of the Line over the Buttons.
      • SetPartingLinesColor (Color As Int) As String
        Change The Parting Lines Color
      • SetSelectedPageColor (color As Int) As String
        Set the color of the icon which is selected
      • SetSlider1Color (color As Int) As String
        Set the slider Color, if the slider slides to the 1. button.
      • SetSlider2Color (color As Int) As String
        Set the slider Color, if the slider slides to the 2. button.
      • SetSlider3Color (color As Int) As String
        Set the slider Color, if the slider slides to the 3. button.
      • SetSlider4Color (color As Int) As String
        Set the slider Color, if the slider slides to the 4. button.
      • SetSlider5Color (color As Int) As String
        Set the slider Color, if the slider slides to the 4. button.
      • SetTabPartingLinesVisible (Visible As Boolean) As String
        Set the Tab Parting Lines Visible. This lines are right or left on the tab vertical.
      • SetText1 (text As String) As String
      • SetText2 (text As String) As String
      • SetText3 (text As String) As String
      • SetText4 (text As String) As String
      • SetText5 (text As String) As String
      • SetTextColor (Color As Int) As String
In the attachment are 3 examples. (B4A,B4I and B4J)

Notes:
-in B4I use the "iXUI" lib.
-BitmapCreator Class is needed

I Plan a second Bottom Menu with Text instead of icons.

Have Fun.

Change log:
- V1.1
  • Badget Value Fits automatic Text Size
  • View Resize Bug Fixed
  • Added Change Middle Button Size
  • Added Hide badget value
- V1.2
  • Fixed Resize Bug on Android
  • Fixed Badget Value Size Bug on Android and IOS
  • Added a 5. Tab, Hides automatically the Middle Button, if this option is true in the designer
  • Slider have now more distance from the icons
- V1.3
  • Add SetTabPartingLinesVisible, shows PartingLines Between the Pages
  • Add SetPartingLinesColor, change the Color of the Parting Lines
  • Add Parting Lines Color in the Designer
  • Important Bug Fixes
- V1.4
  • Add SetMiddleButtonVisible Hide or Show the Middle Button during runtime, pages resize automatically
- V1.5
  • Fix Bug that the pages are not transparent and the background color therefore was not changeable
- V1.6
  • Add Text under the icons (can be activated or deactivated during the runtime)
  • Adds 7 Designer properties and Functions (Text Color, Enable Text and 1-5 Text)
 

Attachments

  • as_bottom_menu android.zip
    22.1 KB · Views: 519
  • as_bottom_menu b4j.zip
    181.2 KB · Views: 279
  • as_bottom_menu ios.zip
    9.8 KB · Views: 235
  • ASBottomMenu.bas
    91.8 KB · Views: 373
Last edited:

asales

Well-Known Member
Licensed User
If I check this option: "Enable Middle Button As Page"
I get this error when I click in every button.

B4X:
java.lang.RuntimeException: Object should first be initialized (B4XBitmap).
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
    at anywheresoftware.b4a.objects.B4XViewWrapper$B4XBitmapWrapper.getWidth(B4XViewWrapper.java:588)
    at as.bottom.menu.asbottommenu._v5(asbottommenu.java:735)
    at as.bottom.menu.asbottommenu._asbm_page_5_handler(asbottommenu.java:370)
    at as.bottom.menu.asbottommenu._asbm_page_5_click(asbottommenu.java:335)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:191)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
    at android.view.View.performClick(View.java:6294)
    at android.view.View$PerformClick.run(View.java:24770)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 

asales

Well-Known Member
Licensed User
One suggestion:
can we have a label to each button, like the image below?
I think will be a great (and customizable) substitute to the NavigationDrawer.
Thanks.

as_buttom4.jpg
 

Alexander Stolte

Expert
Licensed User
I get this error when I click in every button.
you forgot to put an icon on the 5th page. If you enable "Enable Middle Button As Page" then the middle button is hide and a page call "page5" is added. Page5 is always called "page5", no matter if you have set 2 tabs or 4.

can we have a label to each button, like the image below?
that is in the planning, already have a cool idea, but still has time to realize this. (maybe on the weekend) + (with a animation on tab click)

I think will be a great (and customizable) substitute to the NavigationDrawer.
Alone because it is cross platform. :cool::p with the same code you can add this in B4I and B4J.

PD: i like nice menus :)
 

asales

Well-Known Member
Licensed User
you forgot to put an icon on the 5th page. If you enable "Enable Middle Button As Page" then the middle button is hide and a page call "page5" is added. Page5 is always called "page5", no matter if you have set 2 tabs or 4.
That was it.

that is in the planning, already have a cool idea, but still has time to realize this. (maybe on the weekend) + (with a animation on tab click)
Good to know.

PD: i like nice menus :)
+1

Thanks!
 

mindful

Active Member
Licensed User
Hello, first of all I want to congratulate you for your awesome menu.

I am trying to use your class but I have some kind of problems as you can see below:
broken_height.png


The whole view is 640 height and 400 width
The bottom menu is 100 height, anchored vertically to the bottom with a bottom edge distance of 0
The dashboard panel is 540 height, anchored vertically to top and bottom with a bottom edge distance of 100

The problem as you can see is that the menu doesn't fill up to 100 px as it should it only has 62 or so px.

I am using the latest version of b4j.
 

Alexander Stolte

Expert
Licensed User
This is Normal, because, the view is so programmed that the middle button can show whenever you need it (without resizing your layout). Even if you do not need it, you have to take this into account. Maybe I'll change it because I'm rewriting the class right now.

The Pic looks nice, good job Alex. :cool::D:D (Fun)
 

cliv

Member
Licensed User
How can we start without first page selected...(icon color white and no slider)?

NoSelection800.png




Can we have a function:
Page1Enable (True), Page2Enable (False) ......

Enable.png
 

wizard699

Active Member
Licensed User
Hi Alexander.
I've updated to 1.6 versione .... but I've now an errore in sub

Private Sub IconTabs4(Props As Map)

EnableMiddleButtonAsPage = Props.Get("EnableMiddleButtonAsPage")

ERROR:
java.lang.RuntimeException: Cannot parse: null as boolean
at anywheresoftware.b4a.BA.parseBoolean(BA.java:607)
at anywheresoftware.b4a.BA.ObjectToBoolean(BA.java:677)
at net.silca.appsilca.asbottommenu._icontabs4(asbottommenu.java:3014)

What's the problem? Can you help me?

Also your example, with 1.6 version, have the same problem.
 

Brandsum

Well-Known Member
Licensed User
Hello everyone,

I have added some code inside ChangeMiddleButtonSize sub to get a nice curve above the middle button.

Screenshot (Nov 25, 2018 5_46_09 PM).jpg

Here is the code:

B4X:
Public Sub ChangeMiddleButtonSize(size As Double, BorderWidth As Double)
    
    asbm_add_background.Height = size
    asbm_add_background.Width = size
    asbm_add_background.SetColorAndBorder(m_BackgroundColor,BorderWidth,xui.Color_White,asbm_add_background.Height/2)
    
    '''''
    'Code for the curve starts here
    '''''
    'shapes view init
    Dim shape,shapeBack As B4XView
    Dim shapePanel,shapeBackPanel As Panel
    shapePanel.Initialize("shape")
    shapeBackPanel.Initialize("shapeBack")
    
    Dim BezierView,BezierBackView As BitmapCreator
    Dim BezierPath As BCPath
    Dim sWidth As Double = size+200
    Dim sHeight As Double = (size/3) + 20
    
    'draw path
    BezierPath.Initialize(0, sHeight)
    CurveTo(BezierPath, 60, sHeight-1, 90, ((sHeight/3)*2)-5)
    CurveTo(BezierPath, 130, 0, sWidth/2, 1)
    CurveTo(BezierPath, sWidth-130, 0, sWidth-90, ((sHeight/3)*2)-5)
    CurveTo(BezierPath, sWidth-60, sHeight-1, sWidth, sHeight)
    BezierPath.LineTo(0,sHeight)
    
    'draw background
    BezierView.Initialize(sWidth,sHeight)
    BezierView.DrawPath(BezierPath,asbm_page_background.Color,True,0)
    shapePanel.SetBackgroundImage(BezierView.Bitmap).Gravity = Gravity.FILL
    
    'draw border
    BezierBackView.Initialize(sWidth,sHeight)
    BezierBackView.DrawPath(BezierPath,asbm_parting_line.Color,True,0)
    shapeBackPanel.SetBackgroundImage(BezierBackView.Bitmap).Gravity = Gravity.FILL
    
    'set curve view position and background
    shape = shapePanel
    mBase.AddView(shape,(mBase.Width / 2 - sWidth / 2),0, sWidth, sHeight)
    shape.Top = asbm_parting_line.Top - sHeight + 2dip
    shape.Left = asbm_page_background.Width / 2 - shape.Width /2
    shapeBack = shapeBackPanel
    mBase.AddView(shapeBack,(mBase.Width / 2 - sWidth / 2),0, sWidth, sHeight)
    shapeBack.Top = asbm_parting_line.Top - sHeight + 1dip
    shapeBack.Left = asbm_page_background.Width / 2 - shapeBack.Width /2
    shapeBack.SendToBack
    asbm_add_background.BringToFront
    
    '''''
    'Code for the curve ends here
    '''''
    
    'Top position has been modified for the curve view
    asbm_add_background.Top = asbm_parting_line.Top - asbm_add_background.Height/3
    
    asbm_add_background.Left = asbm_page_background.Width / 2 - asbm_add_background.Width /2

    pnl_asbm_add_icon.Width = asbm_add_background.Width /2.5
    pnl_asbm_add_icon.Height = asbm_add_background.Height /2.5
    
    pnl_asbm_add_icon.Left = asbm_add_background.Width / 2 - pnl_asbm_add_icon.Width /2
    pnl_asbm_add_icon.Top = asbm_add_background.Height / 2 - pnl_asbm_add_icon.Height / 2
End Sub

For the CurveTo function check this post by @Erel
https://www.b4x.com/android/forum/threads/b4x-drawing-with-bitmapcreator.98887/#post-622799

I have added the code to ChangeMiddleButtonSize sub to make it flexible as per the button size. So you have to call ChangeMiddleButtonSize inside Activity_Create sub like this:

B4X:
BottomMenu.SetIcon1(FontToBitmap(Chr(0xF015),False,35,Colors.Black))
BottomMenu.SetIcon2(FontToBitmap(Chr(0xF290),False,35,Colors.Black))
BottomMenu.SetIcon3(FontToBitmap(Chr(0xF0F5),False,35,Colors.Black))
BottomMenu.SetIcon4(FontToBitmap(Chr(0xE536),True,40,Colors.Black))
BottomMenu.SetMiddleButtonIcon(FontToBitmap(" SOS ",True,20,Colors.White))
BottomMenu.ChangeMiddleButtonSize(140,0)
BottomMenu.SetPageClickColor(Colors.ARGB(20,10,170,146))

NOTE: You need BitmapCreator V4.50.
 
Top