Android Question [SOLVED] B4XTable Dynamically Show/Hide Column

Jeffrey Cameron

Well-Known Member
Licensed User
I'm having issues showing/hiding a table column after the table has been filled (and yes, I have looked at the examples here and I can replicate this issue using the B4XTableExample program). I've attached a small test program for convenience but the images below will illustrate. Before hiding the column all are visible and there is no left-right scrolling available:
table_before.jpg
After removing the column from the visible columns list and refreshing, it stays in place and the sizing gets messed up and you can scroll left/right:
table_after.jpg
Re-adding the column back into the visible list will make it as it was originally. Interestingly, you can hide the column in the Activity_Create and it will be hidden correctly but you still can't show it again after filling.

Using B4A v9.80 with B4XTable v1.17, XUI v1.92 and XUIViews v2.23. I'm sure there's some finer point in the table documentation that I've missed or I'm not doing something in the correct order, but I'm out of ideas to try at this point.

Any suggestions would be welcome.
 

Attachments

  • TestTable.zip
    10.8 KB · Views: 71
Last edited:

Erel

Administrator
Staff member
Licensed User
This use case will require some additional steps:
B4X:
Private Sub HideColumn(ColID As String)
    Dim poCol As B4XTableColumn = B4XTable1.GetColumn(ColID)
    If poCol <> Null And poCol.IsInitialized Then
        Dim piVisibleColIndex As Int = B4XTable1.VisibleColumns.IndexOf(poCol)
        If piVisibleColIndex >= 0 Then
            B4XTable1.VisibleColumns.RemoveAt(piVisibleColIndex) 'hide column
            B4XTable1.clvData.RemoveAt(piVisibleColIndex)
            poCol.Panel.RemoveViewFromParent
        End If
        B4XTable1.Refresh
    End If
End Sub

Private Sub ShowColumn(ColID As String)
    Dim poCol As B4XTableColumn = B4XTable1.GetColumn(ColID)
    If poCol <> Null And poCol.IsInitialized Then
        Dim piVisibleColIndex As Int = B4XTable1.VisibleColumns.IndexOf(poCol)
        If piVisibleColIndex < 0 Then
            B4XTable1.VisibleColumns.Add(poCol)
            B4XTable1.clvData.Add(poCol.Panel, poCol) '<--- change to InsertAt if you know the index.
        End If
        B4XTable1.Refresh
    End If
End Sub
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
This use case will require some additional steps:
I figured there had to be some step I was missing, I'm not usually this incompotent ;)
Thank you for the help, and I would lobby to have this added to the control as a "hide/showcolumn" method as well because knowing me I'll have this same problem six months from now and not remember how I solved it, LOL!
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
I modified the show function to accept a parameter for index:
B4X:
Private Sub ShowColumn(ColID As String, InsertIndex As Int)
    Dim poCol As B4XTableColumn = B4XTable1.GetColumn(ColID)
    If poCol <> Null And poCol.IsInitialized Then
        Dim piVisibleColIndex As Int = B4XTable1.VisibleColumns.IndexOf(poCol)
        If piVisibleColIndex < 0 Then
            B4XTable1.VisibleColumns.Add(poCol)
            If InsertIndex < 0 Then
                B4XTable1.clvData.Add(poCol.Panel, poCol)
            Else
                B4XTable1.clvData.InsertAt(InsertIndex, poCol.Panel, poCol)
            End If
        End If
        B4XTable1.Refresh
    End If
End Sub
And when I change the show line to:
B4X:
ShowColumn("col3", 2)
it works fine the first time you hide then show the column. The second time, however, it crashes with an error:
B4X:
Error occurred on line: 246 (B4XTable)
java.lang.RuntimeException: Object should first be initialized (View).
 at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
 at anywheresoftware.b4a.objects.B4XViewWrapper.GetView(B4XViewWrapper.java:299)
 at b4a.example3.customlistview._getpanel(customlistview.java:440)
 at b4a.example3.customlistview._resizeitem(customlistview.java:937)
 at b4a.example.testtable.b4xtable._refresh2(b4xtable.java:775)
 at b4a.example.testtable.b4xtable._refresh(b4xtable.java:434)
 at b4a.example.testtable.main._hidecolumn(main.java:557)
 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.BA.raiseEvent(BA.java:176)
 at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
 at android.view.View.performClick(View.java:6300)
 at android.view.View$PerformClick.run(View.java:24941)
 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:6523)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
Did I screw something up?
 

Attachments

  • TestTable.zip
    10.9 KB · Views: 58
Upvote 0

Mahares

Expert
Licensed User
I would lobby to have this added to the control as a "hide/showcolumn" method
Here is a simple, perhaps too simple method to HIDE/UNHIDE col3 which has worked for me. I have not found flaws in it unless someone else can expose. It can probably be modified so any column can be toggled.
B4X:
Private w As Int 'in globals

Dim poCol As B4XTableColumn = B4XTable1.AddColumn("Hide Me", B4XTable1.COLUMN_TYPE_NUMBERS) 'Activity_Create
            poCol.Id = "col3"
            w=poCol.Width

Sub btnTog_Click
            If B4XTable1.GetColumn("col3").Width=1dip Then
                        B4XTable1.GetColumn("col3").Width=w
            Else
                        B4XTable1.GetColumn("col3").Width=1dip
            End If
            B4XTable1.Refresh
End Sub
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Here is a simple
Thank you @Mahares, that does seem to work other than a slightly thicker line where the column is hidden. And it would be simple enough to ignore click events based on visibility should the customer manage to find that 1dip pixel. I had originally attempted this method myself, but I used 0 instead of 1dip which does not work for whatever reason. It didn't occur to me to try 1dip versus 0.

I'd still be interested to see if @Erel has any input on why the other method works fine on the first show/hide cycle but dies on the 2nd one.
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Use B4XTable1.VisibleColumns.InsertAt when you use B4XTable.clvData.InsertAt.
That is indeed the problem, I took your in-code comment too literally. Modifying to the code below works perfectly, and thank you all again for your help!
B4X:
'  Hides the requested column from view.
Public Sub HideColumn(ColID As String)
    Dim poCol As B4XTableColumn = B4XTable1.GetColumn(ColID)
    If poCol <> Null And poCol.IsInitialized Then
        Dim piVisibleColIndex As Int = B4XTable1.VisibleColumns.IndexOf(poCol)
        If piVisibleColIndex >= 0 Then
            B4XTable1.VisibleColumns.RemoveAt(piVisibleColIndex) 'hide column
            If B4XTable1.clvData.IsInitialized Then
                If B4XTable1.clvData.Size > piVisibleColIndex Then
                    B4XTable1.clvData.RemoveAt(piVisibleColIndex)
                End If
            End If
            poCol.Panel.RemoveViewFromParent
        End If
        B4XTable1.Refresh
    End If
End Sub

' Shows a hidden column, if InsertIndex = -1 then the column will be added to the end of the column list.
Public Sub ShowColumn(ColID As String, InsertIndex As Int)
    Dim poCol As B4XTableColumn = B4XTable1.GetColumn(ColID)
    If poCol <> Null And poCol.IsInitialized Then
        Dim piVisibleColIndex As Int = B4XTable1.VisibleColumns.IndexOf(poCol)
        If piVisibleColIndex < 0 Then
            If InsertIndex < 0 Then
                B4XTable1.VisibleColumns.Add(poCol)
                B4XTable1.clvData.Add(poCol.Panel, poCol)
            Else
                B4XTable1.VisibleColumns.InsertAt(InsertIndex, poCol)
                B4XTable1.clvData.InsertAt(InsertIndex, poCol.Panel, poCol)
            End If
        End If
        B4XTable1.Refresh
    End If
End Sub
 
Last edited:
Upvote 0
Top