Scrollview, layouts and getting current selected

bluedude

Well-Known Member
Licensed User
Longtime User
Hi,

I like the scrollview so much that i want to use it to replace my Listviews, simply because it is much more flexible.

What I want to do it taking one layout file and load that one into a scrollview multiple times.

However, I have some practical problems solving my wishes.

- how can I track which layout/panel is clicked?
- is there something like the current clicked item in scrollview?

I have done some settings screens with the scrollview and that works great!

Any suggestions?
 

klaus

Expert
Licensed User
Longtime User
I have tried using a layout for each panel in the scrollview, but no success.
I couldn't set parameters for each view in the layout panel.
EDIT, it works see ScrollViewNLayouts1 below.

I did it similar, but adding each view by code to the panel.

Attached the test program.

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim scvMain As ScrollView
    Dim PanelNb As Int            : PanelNb=20
    Dim PanelHeight As Int    : PanelHeight=50dip
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim i As Int
    
    scvMain.Initialize(500)
    Activity.AddView(scvMain, 0, 0, 100%x, 100%y)
'    Activity.LoadLayout("ScrollViewNLayouts")

    For i=0 To PanelNb-1
        Dim pnltest As Panel
        Dim lblTest As Label
        Dim btnTest As Button
        Dim edtTest As EditText
        
        pnltest.Initialize("pnlTest")
'        pnltest.LoadLayout("Layout")
        scvMain.Panel.AddView(pnltest,0,5dip+i*PanelHeight,100%x,PanelHeight)
        pnltest.Tag=i
        If (i Mod 2)=1 Then
            pnltest.Color=Colors.Red
        Else
            pnltest.Color=Colors.Blue
        End If
        
        lblTest.Initialize("lblTest")
        pnltest.AddView(lblTest,10dip, 5dip, 80dip, 40dip)
        lblTest.Tag=i
        lblTest.TextSize=20
        lblTest.Text="Test "&i
        
        edtTest.Initialize("edtTest")
        pnltest.AddView(edtTest,90dip, 5dip, 110dip, 40dip)
        edtTest.Tag=i
        edtTest.ForceDoneButton=True
        
        btnTest.Initialize("btnTest")
        pnltest.AddView(btnTest,240dip, 5dip, 70dip, 40dip)
        btnTest.Tag=i
        btnTest.Text="Test "&i
    Next
    scvMain.Panel.Height=PanelNb*PanelHeight
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub lblTest_Click
    Dim Send As Label
    
    Send=Sender
    Activity.Title="Label "&Send.Tag
End Sub

Sub btnTest_Click
    Dim Send As Button
    
    Send=Sender
    Activity.Title="Button "&Send.Tag
End Sub

Sub pnlTest_Click
    Dim Send As Panel
    
    Send=Sender
    Activity.Title="Panel "&Send.Tag
End Sub

Sub edtTest_EnterPressed
    Dim Send As EditText
    
    Send=Sender
    Activity.Title="EditText "&Send.Tag&" = "&Send.Text
End Sub
Best regards.

EDIT: Added ScrollViewNLayouts1 with a Panel added for each item and a layout file for the intem Panel
 

Attachments

  • ScrollViewNLayouts.jpg
    ScrollViewNLayouts.jpg
    49.4 KB · Views: 33,223
  • ScrollViewNLayouts.zip
    6.8 KB · Views: 2,051
  • ScrollViewNLayouts1.zip
    7.7 KB · Views: 1,859
Last edited:
Upvote 0

bluedude

Well-Known Member
Licensed User
Longtime User
Yeah I know this workaround but I rather like the designer. If this is the only way to do it then I have no other option.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Here is an example of loading a layout file multiple times.
The Tag property of each view is set to the parent panel. It allows us to find the specific panel.

20110405_1.png


The code (also attached):
B4X:
Sub Process_Globals

End Sub

Sub Globals
    Dim sv As ScrollView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    sv.Initialize(70dip * 10)
    Activity.AddView(sv, 0, 0, 100%x, 100%y)
    For i = 0 To 9
        Dim p As Panel
        p.Initialize("")
        p.Tag = i
        p.LoadLayout("2")
        For v = 0 To p.NumberOfViews - 1
            p.GetView(v).Tag = p 'set the panel as the Tag value
        Next
        sv.Panel.AddView(p, 0, i * 70dip, sv.Panel.Width, 60dip)
    Next
End Sub

Sub button1_click 'handles all buttons
    Dim b As Button
    b = Sender
    Dim p As Panel
    p = b.Tag
    Dim txt As EditText
    txt = GetEditTextOfPanel(p)
    Msgbox("text entered: " & txt.Text, "Panel #" & p.Tag)
End Sub
Sub GetEditTextOfPanel(p As Panel) As EditText
    For i = 0 To p.NumberOfViews - 1
        If p.GetView(i) Is EditText Then Return p.GetView(i)
    Next
End Sub
 

Attachments

  • 1.zip
    5.7 KB · Views: 1,199
Upvote 0

Ennesima77

Member
Licensed User
Longtime User
I take a look on your code and I try to do sominthing similar, but I have a problem.
I need to get the ID when text box lostfocus and store text in a SQL DB, i do this:

B4X:
Sub FillLevel (ID As Int )

   Dim Table As Cursor
   Table = Main.SQLDB.ExecQuery("Select * from DefBlindTableVal where defblindtable = " & ID )
   
   ClearSVLevel
   
   For i = 0 To Table.RowCount - 1
      Table.Position=i
      Dim PanelTMP As Panel 
      PanelTMP=LevelDesign(Table.GetInt2(0),PanellCount, Table)
      svLevel.Panel.AddView(PanelTMP,0,(PanellCount-1)*PanellH ,svLevel.Width, PanellH)
      PanellCount=PanellCount+1
   Next
   
End Sub
Sub ClearSVLevel

   Dim i As Int 
   
   For i = svLevel.Panel.NumberOfViews-1 To 0 Step -1
      svLevel.Panel.RemoveViewAt(i)
   Next
   
   PanellCount=1
   
End Sub
Sub LevelDesign (IDPanel As Int, Order As Int, ActualRow As Cursor ) As Panel 

   Dim pnlLevelTMP As Panel 
   
   Dim lblOrder As Label 
   Dim LabelW As Int : LabelW = 30
   Dim TextH, TextW As Int : TextW = 100 : TextH = 40
   
   pnlLevelTMP.Initialize("pnlLevel")
   pnlLevelTMP.Tag=IDPanel
      
   lblOrder.Initialize("lblOrder")
   pnlLevelTMP.AddView(lblOrder,5dip,5dip,LabelW,Main.BLabelH)
   lblOrder.TextSize=Main.BLabelFS
   lblOrder.Text=Order
   
   txtSB.Initialize("txtSB")
   pnlLevelTMP.AddView(txtSB,lblOrder.Left+lblOrder.Width+Main.ObjDist , _
                  lblOrder.Top, TextW, TextH)
   txtSB.Gravity=Gravity.CENTER 
   txtSB.Tag=IDPanel
   txtSB.InputType= txtSB.INPUT_TYPE_PHONE
   If ActualRow.IsInitialized Then
      txtSB.Text = ActualRow.GetString("SB")
   End If 
   
   txtBB.Initialize("txtBB")
   pnlLevelTMP.AddView(txtBB,txtSB.Left+txtSB.Width+2*Main.ObjDist , _
                  lblOrder.Top, TextW, TextH)
   txtBB.Gravity=Gravity.CENTER 
   txtBB.Tag=IDPanel
   txtBB.InputType= txtBB.INPUT_TYPE_PHONE
   If ActualRow.IsInitialized Then
      txtBB.Text = ActualRow.GetString("BB")
   End If
   
   txtAnte.Initialize("txtAnte")
   pnlLevelTMP.AddView(txtAnte,txtBB.Left+txtBB.Width+2*Main.ObjDist , _
                  lblOrder.Top, TextW, TextH)
   txtAnte.Gravity=Gravity.CENTER 
   txtAnte.Tag=IDPanel
   txtAnte.InputType= txtAnte.INPUT_TYPE_PHONE
   If ActualRow.IsInitialized Then
      txtAnte.Text = ActualRow.GetString("Ante")
   End If
   
   txtTime.Initialize("txtTime")
   pnlLevelTMP.AddView(txtTime,txtAnte.Left+txtAnte.Width+2*Main.ObjDist , _
                  lblOrder.Top, TextW, TextH)
   txtTime.Gravity=Gravity.CENTER 
   txtTime.Tag=IDPanel
   txtTime.InputType= txtTime.INPUT_TYPE_PHONE
   If ActualRow.IsInitialized Then
      txtTime.Text = ActualRow.GetString("Time")
   End If
   
   
   txtPause.Initialize("txtPause")
   pnlLevelTMP.AddView(txtPause,txtTime.Left+txtTime.Width+2*Main.ObjDist , _
                  lblOrder.Top, TextW, TextH)
   txtPause.Gravity=Gravity.CENTER 
   txtPause.Tag=IDPanel
   txtPause.InputType= txtPause.INPUT_TYPE_PHONE
   If ActualRow.IsInitialized Then
      txtPause.Text = ActualRow.GetString("Pause")
   Else
      txtPause.Text = 0
   End If
   
   Return pnlLevelTMP
   
End Sub

With this i populate the scroll view when a BlindLevel (it's a collect of default blind) as selected.
I use some local and main variables to define Label Height or Width and text size, but i suppose this isn't the problem.

B4X:
Sub txtSB_FocusChanged (HasFocus As Boolean)
   
   
   If HasFocus =False Then
      
      Dim WhereMap As Map, Send As EditText 
      Send = Sender
      WhereMap.Initialize 
      WhereMap.Put("id",Send.tag )
      DBUtils.UpdateRecord(Main.SQLDB,SQLBlindTable,"SB",Send.Text ,WhereMap)
      
   End If
   
End Sub

and this is the code in the lost focus event.

But I get just the last Panel in the scrollview and not the current, what's wrong?

Thanks for you kindly reply.
 
Last edited:
Upvote 0

Ennesima77

Member
Licensed User
Longtime User
Yes,
Send.tag gave me only the lastone index and Send.Text gave me only last Text.
Es:
1 50 100
2 100 200
3 200 400
4 300 600

in the first row (1)Send.tAG return me 4 and Send.Text 300 (and I expect 50).
I will try to made a button to save the record (the complet row), but in my first intection it's better save the data at lostfocus of each single TextBox.

Just another strange function:

I perform the same code in 2 differt activity
In one the tab order is orizzontal, in the other one is vertical:

1 50 100
2 100 200
3 200 400
4 300 600

1 50 100
2 100 200
3 200 400
4 300 600

When a press "Next" on tablet

1 50 100
2 100 200
3 200 400
4 300 600

1 50 100
2 100 200
3 200 400
4 300 600

the only differts i in the first case SladeView is a 50%X and 100%y on the right of the screen, in the second one it's 50%x and 70%y in the bottom left corner of the screen.

Thanks for you reply.
 
Upvote 0

Ennesima77

Member
Licensed User
Longtime User
Solved the first problem!
I declared the txtSB and other EditText in Globals as I use to do with the others object.
If I declare them in the LevelDesign sub it works fine!

Second problem it's steel a mistery, i mean tab order!
Thanks!
 
Upvote 0

onikudaki

Member
Licensed User
Longtime User
Hi Erel,

just a quick question regarding the method you have demonstrated, using a layout for each item in the list.

I have this working, but am having some issues with setting values of individual items.

I've tried using the code

B4X:
Sub button1_click 'handles all buttons
    Dim b As Button
    b = Sender
    Dim p As Panel
    p = b.Tag
    Dim txt As EditText
    txt = GetEditTextOfPanel(p)
    Msgbox("text entered: " & txt.Text, "Panel #" & p.Tag)
End Sub
Sub GetEditTextOfPanel(p As Panel) As EditText
    For i = 0 To p.NumberOfViews - 1
        If p.GetView(i) Is EditText Then Return p.GetView(i)
    Next
End Sub

to guide me, but I cant seem to get the correct controls :(

in my case, I have a number of entries, each with a label, which I need to be able to update on an ad-hoc basis.

any thoughts or advice would be good.

thanks
Oni (steve)
 
Upvote 0
Top