Android Question [SOLVED] Background color in a scrollview with 5 columns

antonomase

Active Member
Licensed User
Longtime User
Hello,
I'm trying to build a ScrollView with 5 columns.
In B4XMainPage, I have a function CreateMainList wich create the ScrollView, define the definitions of cols, create the line of title and populate the ScrollView

B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    B4XPages.SetTitle(Me, "Test List")
    CreateMainList
End Sub

Sub CreateMainList ()
    scroll.Initialize(0)

    'Create scrollView and panel
    Dim pnl As Panel
    Dim height = 50dip As Int
    pnl = scroll.Panel
    Root.AddView(scroll, 0, 0, 100%x, 100%y)

    DefineScrollColls
    CreateScrollTitle (pnl, height)
    Populate (pnl, height)
End Sub

Before storing the data, the function DefineScrollColls checks if the process_global ObjectSize exists and if it is filled in. This way, I can be sure (normally) that column widths remain fixed.
B4X:
Sub DefineScrollColls()
    ' Position x and width
    Dim x(5), w(5) As Int
    x = Array As Int(0, 10%x, 20%x, 70%x, 85%x)
    w = Array As Int(10%x, 10%x, 50%x, 15%x, 15%x)
  
    ' Title of columns 
    Dim t(5) As String
    t = Array As String("Tr", "Dup", "List", "Date", "Num")
  
    ' Color of title (radius for testing)
    Dim bckColorTitle As ColorDrawable
    bckColorTitle.Initialize(0xFF3A5FCD, 50)

    ' Color of lines
    Dim bckColorEven As ColorDrawable
    bckColorEven.Initialize(0xFFCCCCCC, 50)
  
    ' Store the caracteristics of columns
    If Not(Main.ObjectSize.IsInitialized) Then
        Main.ObjectSize.Initialize
    End If
    If Not(Main.ObjectSize.ContainsKey("scroll.col0.X")) Then
        For i = 0 To x.Length - 1
            Main.ObjectSize.Put($"scroll.col${i}.X"$, x(i))
            Main.ObjectSize.Put($"scroll.col${i}.Width"$, w(i))
            Main.ObjectSize.Put($"scroll.col${i}.Title"$, t(i))
            Main.ObjectSize.Put($"scroll.col${i}.Gravity"$, Gravity.CENTER)
            Main.ObjectSize.Put($"scroll.col${i}.TitleBackground"$, bckColorTitle)
            Main.ObjectSize.Put($"scroll.col${i}.Background"$, bckColorEven)
        Next
    End If
End Sub

Here is the code for the creating the 1st line
B4X:
Sub CreateScrollTitle (pnl As Panel, height As Int)
    Dim lbl(5) As Label
    For i = 0 To lbl.Length -1
        lbl(i).Initialize("")
        lbl(i).Text = Main.ObjectSize.Get($"scroll.col${i}.Title"$)
        lbl(i).Gravity = Main.ObjectSize.Get($"scroll.col${i}.Gravity"$)
        lbl(i).Background = Main.ObjectSize.Get($"scroll.col${i}.TitleBackground"$)
        pnl.AddView(lbl(i), Main.ObjectSize.Get($"scroll.col${i}.X"$), 0, Main.ObjectSize.Get($"scroll.col${i}.Width"$), height)
    Next
End Sub


Then a Populate function that adds rows in a similar way

My inspiration comes from https://www.b4x.com/android/forum/threads/list-with-two-columns-and-a-checkbox.7221/#post41354

When I run the application, it's OK, my columns are just as I asked (image 1).
1st.png


But if I switch to another application and come back, the label positions don't change, but the backgrounds do: those in columns 1 and 2 seem longer, those in column 3 seem shorter, those in columns 4 and 5 don't change.
after.png

I
This was tested on a Google Pixel and a Samsung tablet with the same behavior. I've been on it for two days. I tried with AutoScaleAll and without AutoScaleAll. Nothing works.

Can anyone point me in the right direction?

Best regards
 

Attachments

  • TestScroll.zip
    67.6 KB · Views: 36

klaus

Expert
Licensed User
Longtime User
I had a look at your code.

1. You should not put anything in the Main module.
You should declare ObjectSize Map in B4XMainPage instead of Main.

2. You must move the declarations of the ColorDrawables into the For / Next loop one for each row.
B4X:
        For i = 0 To x.Length - 1
            ' Color of title (radius for testing)
            Dim bckColorTitle As ColorDrawable
            bckColorTitle.Initialize(0xFF3A5FCD, 50)

            ' Color of lines
            Dim bckColorEven As ColorDrawable
            bckColorEven.Initialize(0xFFCCCCCC, 50)

            ObjectSize.Put($"scroll.col${i}.X"$, x(i))
            ObjectSize.Put($"scroll.col${i}.Width"$, w(i))
            ObjectSize.Put($"scroll.col${i}.Title"$, t(i))
            ObjectSize.Put($"scroll.col${i}.Gravity"$, Gravity.CENTER)
            ObjectSize.Put($"scroll.col${i}.TitleBackground"$, bckColorTitle)
            ObjectSize.Put($"scroll.col${i}.Background"$, bckColorEven)
        Next
    End If

3. In bckColorTitle.Initialize(0xFF3A5FCD, 50) and bckColorEven.Initialize(0xFFCCCCCC, 50) you are missing dip values.
You might define the height variable as global and use height / 2 instead of 50.
Then 50 is supposed to be the Radius, but your height if 50dip, therefore it should be 25dip.
 
Upvote 0

antonomase

Active Member
Licensed User
Longtime User
Thanks for telling me to put the ColorDrawable into the loops.

I change the code

B4X:
Sub DefineScrollColls()
    ' Position x and width
    Dim x(5), w(5) As Int
    x = Array As Int(0, 10%x, 20%x, 70%x, 85%x)
    w = Array As Int(10%x, 10%x, 50%x, 15%x, 15%x)
    
    ' Title of columns   
    Dim t(5) As String
    t = Array As String("Tr", "Dup", "List", "Date", "Num")
    
    ' Store the caracteristics of columns
    If Not(ObjectSize.IsInitialized) Then
        ObjectSize.Initialize
    End If
    If Not(ObjectSize.ContainsKey("scroll.col1.X")) Then
        For i = 0 To x.Length - 1
            ObjectSize.Put($"scroll.col${i}.X"$, x(i))
            ObjectSize.Put($"scroll.col${i}.Width"$, w(i))
            ObjectSize.Put($"scroll.col${i}.Title"$, t(i))
            ObjectSize.Put($"scroll.col${i}.Gravity"$, Gravity.CENTER)
            ObjectSize.Put($"scroll.col${i}.TitleBackground"$, 0xFF3A5FCD) '  Store the color
            ObjectSize.Put($"scroll.col${i}.Background"$, 0xFFCCCCCC)
        Next
    End If
End Sub

B4X:
Sub CreateScrollTitle (pnl As Panel, height As Int)
    Dim lbl(5) As Label
    For i = 0 To lbl.Length -1
        lbl(i).Initialize("")
        lbl(i).Text = ObjectSize.Get($"scroll.col${i}.Title"$)
        lbl(i).Gravity = ObjectSize.Get($"scroll.col${i}.Gravity"$)
        Dim color As ColorDrawable
        color.Initialize(ObjectSize.Get($"scroll.col${i}.TitleBackground"$), 50)
        lbl(i).Background = color
        pnl.AddView(lbl(i), ObjectSize.Get($"scroll.col${i}.X"$), 0, ObjectSize.Get($"scroll.col${i}.Width"$), height)
    Next
End Sub
and similar into Populate into the inner loop

To answer other questions

1) If I put ObjectSize in Main, it's because I'm going to use the values in many other pages, which in turn will also enrich ObjectSize. This Map will be manipulated in many pages.
Is there a simple solution that avoids this?
3) The radius value of 50 was just to visually see where there were errors. In the final code, the value will be 0.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
When you declare something Public in B4XMainPage you can access it from any other Page with B4XPages.MainPage like:
B4X:
B4XPages.MainPage.ObjectMap.Size

If you have many lines where you want to access B4XMainPage you can define a variable for it like below:
B4X:
Sub Class_Globals
    Private Root As B4XView 'ignore
    Private xui As XUI 'ignore
   
    Private MP As B4XMainPage
End Sub

'You can add more parameters here.
Public Sub Initialize As Object
    Return Me
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
    MP = B4XPages.MainPage

    Log(B4XPages.MainPage.ObjectSize.Size)    'long version
    Log(MP.ObjectSize.Size)                                    'short version
End Sub
 
Upvote 0
Top