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: 777
  • as_bottom_menu b4j.zip
    181.2 KB · Views: 512
  • as_bottom_menu ios.zip
    9.8 KB · Views: 472
  • ASBottomMenu.bas
    91.8 KB · Views: 610
Last edited:

Brandsum

Well-Known Member
Licensed User
@ciprian Sorry I can't share that project in which I've used this custom view class. Though I've already posted the modified code. You can download the latest version of this custom view class and can add that modified code to achieve the curve above the middle button.
 

ciprian

Active Member
Licensed User
Longtime User
This is what i've allready tried, but i don't find the ChangeMiddleButtonSize sub.
I will retry this morning.
Thank you.
 

ciprian

Active Member
Licensed User
Longtime User
Done. But now i'm getting many errors, i'm surely missing something.
I attached my modified project, i'm using B4A V8.80, library used: bitmapcreator 4.50, core 8.80, JavaObject 2.05, XUI 1.90.
 

Attachments

  • AS_Bottom_Menu_test.zip
    42.7 KB · Views: 232

Brandsum

Well-Known Member
Licensed User
Seems that you have not followed what I posted.

FontToBitmap
is missing in your project. It's a function to create a bitmap from icon font.

B4X:
Public Sub FontToBitmap (text As String, IsMaterialIcons As Boolean, FontSize As Float, color As Int) As B4XBitmap
    Dim xui As XUI
    Dim p As B4XView = xui.CreatePanel("")
    p.SetLayoutAnimated(0, 0, 0, 32dip, 32dip)
    Dim cvs1 As B4XCanvas
    cvs1.Initialize(p)
    Dim t As Typeface
    If IsMaterialIcons Then t = Typeface.MATERIALICONS Else t = Typeface.FONTAWESOME
    Dim fnt As B4XFont = xui.CreateFont(t, FontSize)
    Dim r As B4XRect = cvs1.MeasureText(text, fnt)
    Dim BaseLine As Int = cvs1.TargetRect.CenterY - r.Height / 2 - r.Top
    cvs1.DrawText(text, cvs1.TargetRect.CenterX, BaseLine, fnt, color, "CENTER")
    Dim b As B4XBitmap = cvs1.CreateBitmap
    cvs1.Release
    Return b
End Sub
CurveTo function is missing too. Copy that above ChangeMiddleButtonSize
B4X:
'Curve function
Private Sub CurveTo (Path1 As BCPath, ControlPointX As Float, ControlPointY As Float, TargetX As Float, TargetY As Float)
    Dim LastPoint As InternalBCPathPointData = Path1.Points.Get(Path1.Points.Size - 1)
    Dim CurrentX As Float = LastPoint.X
    Dim Currenty As Float = LastPoint.Y
    Dim NumberOfSteps As Int = 8 '<--- change as needed
    Dim dt As Float = 1 / NumberOfSteps
    Dim t As Float = dt
    For i = 1 To NumberOfSteps
        Dim tt1 As Float =  (1 - t) * (1 - t)
        Dim tt2 As Float = 2 * (1 - t) * t
        Dim tt3 As Float = t * t
        Dim x As Float = tt1 * CurrentX + tt2 * ControlPointX + tt3 * TargetX
        Dim y As Float = tt1 * Currenty + tt2 * ControlPointY + tt3 * TargetY
        Path1.LineTo(x, y)
        t = t + dt
    Next
End Sub
And remove the Bitmapcreator.bas from your project.
 
Last edited:

ciprian

Active Member
Licensed User
Longtime User
Thank you, it done now. But an error persists into ASBottomMenu module,
B4X:
    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)
The "CurveTo" function : undeclared variable CurveTo is used before it was assigned any value.
 

Brandsum

Well-Known Member
Licensed User
Thank you, it done now. But an error persists into ASBottomMenu module,
B4X:
    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)
The "CurveTo" function : undeclared variable CurveTo is used before it was assigned any value.
Did you added CurveTo function above ChangeMiddleButtonSize?
 

ciprian

Active Member
Licensed User
Longtime User
I've added you code into ASBottomMenu module as like this:
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
 

ciprian

Active Member
Licensed User
Longtime User
Sorry, i see it now.
I get an error in compilation:
B4X:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Class not found: b4a.example.asbottommenu, trying: as.bottom.menu.asbottommenu
Error occurred on line: 153 (ASBottomMenu)
java.lang.RuntimeException: Cannot parse: null as boolean
    at anywheresoftware.b4a.BA.parseBoolean(BA.java:612)
    at anywheresoftware.b4a.BA.ObjectToBoolean(BA.java:682)
    at as.bottom.menu.asbottommenu._icontabs4(asbottommenu.java:3235)
    at as.bottom.menu.asbottommenu._designercreateview(asbottommenu.java:2672)
    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:144)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:180)
    at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:61)
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:162)
    at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:209)
    at as.bottom.menu.main._activity_create(main.java:383)
    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:144)
    at as.bottom.menu.main.afterFirstLayout(main.java:104)
    at as.bottom.menu.main.access$000(main.java:17)
    at as.bottom.menu.main$WaitForLayout.run(main.java:82)
    at android.os.Handler.handleCallback(Handler.java:789)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6541)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
** Activity (main) Resume **

Looks like the class is not found, but it's beeing there.
I've attached modiffied project.
 
Last edited:

RWK

Member
Licensed User
B4X:
    Dim shapePanel,shapeBackPanel As Panel

This is not B4X aware. Maybe you could change it to work in B4J also?
 
Top