Android Question Multiple buttons evenly distributed

Sergio Haurat

Active Member
Licensed User
Longtime User
Using this example from @Erel

I am trying to draw on the screen 32 buttons in 4 rows and 8 columns.
In the designer there is only one panel to contain the buttons.
1692370246026.png


This is the code:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private pnlButtons As B4XView
    Type btnObj (Text As String, Tag As Object)
End Sub

Private Sub B4XPage_Appear
    Dim intCnt As Int = 0
    Dim intSize As Int = ButtonSize
    For col = 0 To 3
        For row = 0 To 7
            Dim btnProp As btnObj
            btnProp.Initialize
            btnProp.Text = col.As (String) & "," & row.As (String)
            btnProp.Tag = intCnt
            pnlButtons.AddView(ButtonsCreator(btnProp), row * intSize, col * intSize, intSize, intSize)
            intCnt = intCnt + 1
        Next
    Next
End Sub

Private Sub B4XPage_Created (RootMain As B4XView)
    Root = RootMain
    Root.LoadLayout("MainPage")
End Sub

Private Sub ButtonsCreator(btnProp As btnObj) As Button
    Dim b As Button
    b.Initialize("btn")
    b.Text = btnProp.Text
    b.Tag = btnProp.Tag
    Return b
End Sub

Private Sub ButtonSize() As Int
    Dim intSize As Int = 0
    'This is where I should calculate the width and height of the button, according to the width and height of the device the size that suits each button
    intSize = 200
    Return intSize
End Sub

Private Sub btn_Click
    ToastMessageShow(Sender.As (Button).Tag,False)
End Sub
 
Last edited:

Sergio Haurat

Active Member
Licensed User
Longtime User
This is the best way?:
Private Sub ButtonSize() As Int
    Dim intSize As Int = 0
    Dim intWidth As Int = (pnlButtons.Width / 8)
    Dim intHeight As Int = (pnlButtons.Height / 4)
    If intHeight > intWidth Then
        intSize = intWidth
    Else
        intSize = intHeight
    End If
    Return intSize
End Sub
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
Final Code:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private pnlButtons As B4XView
    Type btnObj (Text As String, Tag As Object)
    Private intCols As Int = 6
    Private intRows As Int = 3
End Sub

Public Sub Initialize
    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Appear
    Dim intCnt As Int = 0
    Dim intSize As Int = ButtonSize
    For row = 0 To intRows - 1
      For col = 0 To intCols - 1
            Dim btnProp As btnObj
            btnProp.Initialize
            btnProp.Text = col.As (String) & "," & row.As (String)
            btnProp.Tag = intCnt
            pnlButtons.AddView(ButtonsCreator(btnProp), col * intSize, row * intSize, intSize, intSize)
            intCnt = intCnt + 1
        Next
    Next
End Sub

Private Sub B4XPage_Created (RootMain As B4XView)
    Root = RootMain
    Root.LoadLayout("MainPage")
End Sub

Private Sub ButtonsCreator(btnProp As btnObj) As Button
    Dim b As Button
    b.Initialize("btn")
    b.Text = btnProp.Text
    b.Tag = btnProp.Tag
    Return b
End Sub

Private Sub ButtonSize() As Int
    Dim intSize As Int = 0
    Dim intWidth As Int = (pnlButtons.Width / intCols)
    Dim intHeight As Int = (pnlButtons.Height / intRows)
    If intHeight > intWidth Then
        intSize = intWidth
    Else
        intSize = intHeight
    End If
    Return intSize
End Sub

Private Sub btn_Click
    ToastMessageShow(Sender.As (Button).Tag,False)
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Using this example from @Erel
Why are you referring to and using a very old thread that is over 12 years old. Have you considered an xClv which can fit on one screen and has 8 columns and four rows of buttons in a panel set up in the designer. I think it will be a lot more up to date and more versatile and modern. Maybe something that looks like this.

1692379117979.png

Since you already chose your code as a solution, can you at least show a snapshot of what it looks like.
 
Upvote 0

josejad

Expert
Licensed User
Longtime User
Take a look to this, too

 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
Why are you referring to and using a very old thread that is over 12 years old. Have you considered an xClv which can fit on one screen and has 8 columns and four rows of buttons in a panel set up in the designer. I think it will be a lot more up to date and more versatile and modern. Maybe something that looks like this.

View attachment 144906
Since you already chose your code as a solution, can you at least show a snapshot of what it looks like.
I had not seen since when the post was, 12 years old is a lot. I only saw the code. And it's not the first time this has happened to me either (take an example from an old post, to be honest)

@Mahares, can you share your code? I'm struggling with "my old code base" to set the font, borders, images and other properties.

By mistake I marked the post as solved.
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
Although I've known B4A originally since 2014, I remember getting "angry" when the screen would rotate, the activity would lose the value of the objects and you had to save the values doing Chinese juggling with other components or something like that (bad decision to stay away for so long). . Thanks to all of you, help sort my knowledge with today.
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
There is a small problem in your source code: it will create and add new buttons every time the page appears (B4XPage_Appear!).


Did you know that in a B4XPage project you can only have one orientation, vertical or horizontal (unless you create another Activity in addition to the Main)?
Yes, I know, but my problem was a long time ago, before B4XPage's existed.
There is a small problem in your source code: it will create and add new buttons every time the page appears (B4XPage_Appear!).

The variables (IntCols and IntRows) should actually be a user option, ie you can decide how many buttons to show.

For example
5x3
8x4

Last version of my code:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private pnlButtons As B4XView
    Type btnObj (Text As String, Tag As Object, Picture As Bitmap, Padding As Int, Font As B4XFont)
    Private intCols As Int = 8
    Private intRows As Int = 4
End Sub

Public Sub Initialize
    B4XPages.GetManager.LogEvents = True
    
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Appear

End Sub

Private Sub B4XPage_Created (RootMain As B4XView)
    Root = RootMain
    Root.LoadLayout("MainPage")
    B4XPages.SetTitle(Me, Main.loc.Localize("app_name"))
    ButtonShow
End Sub

Private Sub ButtonsCreator(btnProp As btnObj) As Button
    Dim b As Button
    b.Initialize("btn")
    b.Text = btnProp.Text
    b.TextSize = btnProp.Font.Size
    b.Tag = btnProp.Tag
    b.SingleLine =False
    b.Padding = Array As Int (btnProp.Padding, btnProp.Padding, btnProp.Padding, btnProp.Padding)
    If btnProp.Picture.IsInitialized Then
        b.SetBackgroundImage(btnProp.Picture)
    End If
    Return b
End Sub

Private Sub ButtonShow()
    Dim intSize As Int = ButtonSize(200, 40)
    pnlButtons.SetLayoutAnimated(0, (Root.Width - (intSize * intCols)) / 2, (Root.Height - (intSize * intRows)) / 2, (intSize * intCols), (intSize * intRows))
    Dim intCnt As Int = 0
    For row = 0 To intRows - 1
        For col = 0 To intCols - 1
            Dim btnProp As btnObj
            btnProp.Initialize
            btnProp.Text = row.As (String) & "," & col.As (String)
            btnProp.Tag = intCnt
            btnProp.Padding = 2
            btnProp.Picture = LoadBitmap(File.DirAssets, "logo.png").Resize(intSize, intSize, True)
            pnlButtons.AddView(ButtonsCreator(btnProp), col * intSize, row * intSize, intSize, intSize)
            intCnt = intCnt + 1
        Next
    Next
End Sub

Private Sub ButtonSize(SafeAreaW As Int, SafeAreaH As Int) As Int
    Dim intSize As Int = 0
    Dim intWidth As Int = (Root.Width / intCols) - (SafeAreaW / intCols)
    Dim intHeight As Int = (Root.Height / intRows) - (SafeAreaH / intRows)
    If intHeight > intWidth Then
        intSize = intWidth
    Else
        intSize = intHeight
    End If
    Return intSize
End Sub

Private Sub btn_Click
    ToastMessageShow("Acción: " & Sender.As (Button).Tag, False)
End Sub

Private Sub btn_LongClick
    ToastMessageShow("Configuración: " & Sender.As (Button).Tag, False)
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
One way that might be simpler than the way you are trying to do it is to create a layout with one panel and inside it 8 evenly spaced buttons horizontally using the designer as outlined to you by Jose in, post #5. Then clone that panel 3 times to obtain the look you want. I still prefer the xClv way, but this cloning is in line with what you are trying to achieve. Here is a teaser:
1692490174719.png











45
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
?
1692556202525.png


 
Upvote 0
Top