Android Code Snippet [B4X] B4XTable - Resize columns based on content

Discussion in 'Code Snippets' started by Erel, Feb 14, 2019.

  1. Erel

    Erel Administrator Staff Member Licensed User

    This code measures the required width based on the cells text and set it:

    Code:
    Sub B4XTable1_DataUpdated
       
    Dim ShouldRefresh As Boolean
      
    'NameColumn and NumberColumn are global B4XTableColumns that we want to measure
       For Each Column As B4XTableColumn In Array(NameColumn, NumberColumn)
           
    Dim MaxWidth As Int
           
    For i = 0 To B4XTable1.VisibleRowIds.Size
               
    Dim pnl As B4XView = Column.CellsLayouts.Get(i)    
               
    Dim lbl As B4XView = pnl.GetView(0)
               MaxWidth = 
    Max(MaxWidth, cvs.MeasureText(lbl.Text, lbl.Font).Width + 10dip)
           
    Next
           
    If MaxWidth > Column.ComputedWidth Or MaxWidth < Column.ComputedWidth - 20dip Then
               Column.Width = MaxWidth
               ShouldRefresh = 
    True
           
    End If
       
    Next
       
    If ShouldRefresh Then
           B4XTable1.Refresh
       
    End If
    End Sub
    cvs is a global B4XCanvas. Create it with this code when the app starts:
    Code:
    Dim p As B4XView = xui.CreatePanel("")
       p.SetLayoutAnimated(
    0001dip1dip)
       cvs.Initialize(p)
     
    Last edited: Feb 15, 2019
    DonManfred, LucaMs and BillMeyer like this.
  2. LucaMs

    LucaMs Expert Licensed User

    What are NameColumn and NumberColumn?

    Why a code snippet instead of a new b4xTable method?
     
  3. Mahares

    Mahares Well Known Member Licensed User

    I am getting this error:
    java.lang.ClassCastException: java.lang.String cannot be cast to carthage.lastvisitb4xtable.b4xtable$_b4xtablecolumn
    at this line:
    Code:
    For Each Column As B4XTableColumn In Array(NameColumn, NumberColumn) 'of SUb B4XTable1_DataUpdated
    Here is part of the code:
    Code:
    Sub Globals
        
    Private B4XTable1 As B4XTable
        
    Private cvs As B4XCanvas
        
    Private xui As XUI
        
    Private NameColumn As String
        
    Private NumberColumn As Int  'it does not like this declaration
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    Activity.LoadLayout("1")  'has the B4XTable customview
        Dim p As B4XView = xui.CreatePanel("")
        p.SetLayoutAnimated(
    0001dip1dip)
        cvs.Initialize(p)
    .
    .
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    1:
    Code:
    Private NameColumn As B4XTableColumn
    2:
    Code:
    NameColumn = B4XTable.AddColum(...)
     
    LucaMs likes this.
  5. Erel

    Erel Administrator Staff Member Licensed User

    Not every feature is immediately added to the library. It might be added in the future.
     
    LucaMs likes this.
  6. Mahares

    Mahares Well Known Member Licensed User

    I still cannot get it to work. Here is the error. Am I the only dude that does not get it or what:
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object anywheresoftware.b4a.objects.collections.List.Get(int)' on a null object reference
    Code:
    Sub Globals
    Private NameColumn As B4XTableColumn
        
    Private NumberColumn As Int   'What is this suppoed to be. It says variable is never assigned any value.
    Could you please explain better this code snippet and provide a small example on how to automatically adjust columns width.
     
  7. DonManfred

    DonManfred Expert Licensed User

    You should tell us. It is from your Code or not?
     
  8. DonManfred

    DonManfred Expert Licensed User

    Based on this code NumberColumn must be the same type as NameColumn (B4XTableColumn), So in fact
    In the code NameColumn and NumberColumn are measured.

    PD;: Sorry, i never worked with B4XTable, i just saw the Release and some threads about. But that´s all.
     
  9. Mahares

    Mahares Well Known Member Licensed User

    Private NumberColumn As Int 'What is this suppoed to be. It says variable is never assigned any value.
    NumberColumn is a variable in Erel's snippet.
     
  10. LucaMs

    LucaMs Expert Licensed User

    Given its name, you could think that NumberColumn is a column number.
    It must be the column (b4xTableColumn type) you want to resize and you get it as "function result" when you CREATE and add a new column to the table using the method/function AddColumn.


    Code from the b4xTable example, modified to test the snippet:
    Code:
    Sub Globals
       
    Private B4XTable1 As B4XTable
       
    Private xui As XUI
       
    Private mNumberColumn As B4XTableColumn ' I renamed it adding the prefix "m"
       Private btnPrev As Button
       
    Private btnNext As Button
       
    Private IME As IME
     
       
    Private mcvs As B4XCanvas ' Added; even here I'm using the prefix "m"
       Private mNameColumn As B4XTableColumn ' Added
    End Sub


    ' Activity_Create
    '...
    'create the columns
        'B4XTable1.AddColumn("US County", B4XTable1.COLUMN_TYPE_NUMBERS)' Original line
        mNameColumn = B4XTable1.AddColumn("US County", B4XTable1.COLUMN_TYPE_NUMBERS) ' new line
        B4XTable1.AddColumn("Name", B4XTable1.COLUMN_TYPE_TEXT)
        
    Dim StateColumn As B4XTableColumn = B4XTable1.AddColumn("State", B4XTable1.COLUMN_TYPE_TEXT)
        StateColumn.Width = 
    80dip
        mNumberColumn = B4XTable1.AddColumn(
    "Interesting Number", B4XTable1.COLUMN_TYPE_NUMBERS)
    Then in the snippet:
    Code:
    For Each Column As B4XTableColumn In Array(mNameColumn, mNumberColumn) 'change the columns that should be measured
     
  11. Mahares

    Mahares Well Known Member Licensed User

    I think I got is figured out using this code. It is working for me now after several hours:
    Code:
    Sub Globals
        
    Private B4XTable1 As B4XTable  
        
    Private cvs As B4XCanvas
        
    Private xui As XUI
        
    Private NameColumn(6As B4XTableColumn
    End Sub
    Code:
    NameColumn(0) = B4XTable1.AddColumn("Name", B4XTable1.COLUMN_TYPE_TEXT)
        NameColumn(
    1) = B4XTable1.AddColumn("Customer Id", B4XTable1.COLUMN_TYPE_NUMBERS)
        NameColumn(
    2) = B4XTable1.AddColumn("Company", B4XTable1.COLUMN_TYPE_TEXT)
        NameColumn(
    3) = B4XTable1.AddColumn("Address", B4XTable1.COLUMN_TYPE_TEXT)
        NameColumn(
    4) = B4XTable1.AddColumn("Email", B4XTable1.COLUMN_TYPE_TEXT)
        NameColumn(
    5) = B4XTable1.AddColumn("Country", B4XTable1.COLUMN_TYPE_TEXT)
    Code:
    Sub B4XTable1_DataUpdated
        
    Dim ShouldRefresh As Boolean
        
    For Each Column As B4XTableColumn In Array (NameColumn(0), NameColumn(1), NameColumn(2), NameColumn(3), NameColumn(4), NameColumn(5) )
            
    Dim MaxWidth As Int
            
    For i = 0 To B4XTable1.VisibleRowIds.Size
                
    Dim pnl As B4XView = Column.CellsLayouts.Get(i)
                
    Dim lbl As B4XView = pnl.GetView(0)
                MaxWidth = 
    Max(MaxWidth, cvs.MeasureText(lbl.Text, lbl.Font).Width + 10dip)
            
    Next
            
    If MaxWidth > Column.ComputedWidth Or MaxWidth < Column.ComputedWidth - 20dip Then
                Column.Width = MaxWidth
                ShouldRefresh = 
    True
            
    End If
        
    Next
        
    If ShouldRefresh Then
            B4XTable1.Refresh
        
    End If
    End Sub
     
  12. LucaMs

    LucaMs Expert Licensed User

    I'm sorry to have written my post not many minutes ago, which should be quite clear.

    You can change this line to:
    Code:
    For Each Column As B4XTableColumn In NameColumn
    I would also change the array name from NameColumn to Columns.
     
  13. Mahares

    Mahares Well Known Member Licensed User

    Hi Mario:
    The reason I wanted to explicitly show the columns is because in the official project, I wanted to skip autowidth for some columns. That is why I did this:
    Code:
    For Each Column As B4XTableColumn In Array (NameColumn(0),  NameColumn(2), NameColumn(5) )
    not simply use the full array as below:
    Code:
    For Each Column As B4XTableColumn In (NameColumn)
    I think the main reason I had trouble with Erel's snippet is this:
    Array(NameColumn, NumberColumn)
    If he wrote: Array(NameColumn1, NameColumn3, NameColumn6, etc.)I would have understood it. But we can't blame him as he answers a ton of posts each day and that is taxing.
     
    Last edited: Feb 14, 2019
  14. Erel

    Erel Administrator Staff Member Licensed User

    The first code snippet did include a comment which was later removed by mistake when I updated the code. I've added it back now.
     
    jimmyF and DonManfred like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice