Android Question GetAllViewsRecursive

LucaMs

Expert
Licensed User
Longtime User
I developed an example project for an italian member (this is the reason why the project attached to this post is in Italian).

To retrieve all the labels added in a panel by Designer and put them in an array, I used GetAllViewsRecursive:
B4X:
' Globals
Private arrLabels(90) As Label


' Activity_Create
Dim Index As Int = 0

For Each lbl As Label In pnlLabels.GetAllViewsRecursive
    arrLabels(Index) = lbl
    lbl.Text = Index + 1
    lbl.Tag = Index + 1
    Index = Index + 1
Texts and Tags will be right but the array seems to be composed only of last label (all references to the last label).


I solved using:
B4X:
For I = 0 to pnlLabels.NumberOfViews - 1
    Dim lbl As Label = pnlLabels.Get(I)
    arrLabels(Index) = lbl
    lbl.Text = Index + 1
    lbl.Tag = Index + 1
    Index = Index + 1

but I don't understand why you can successfully change some properties of the "current label" into the loop but the addition to the array fails.



[In the project, "Estrai" creates a list of 5 random number, which must be highlighted]
 

Attachments

  • GetAllViewsRecursive.zip
    10.6 KB · Views: 185
Last edited:

sorex

Expert
Licensed User
Longtime User
it probably freaks out because you didn't declare the array as an array of labels

B4X:
Private arrLabels(90)

'should be

Private arrLabels(90) as label

I think everything undeclared falls back to string type.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
maybe the for each uses a temporary label reference that gets removed after the loop
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
maybe the for each uses a temporary label reference that gets removed after the loop
Something like that, but not exactly, because the reference, though temporary, points to the right label. As you can see, I change the properties of lbl, which is the referenced label, not of the label of the array (which should be the same, moreover), and the changes are correct.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
then it's using 1 dim l as label at the start of the for each where it puts the actually label reference in.

and when you store that 10 times the last label will be referenced to when you use arrLabels(0) or arrLabels(66).

an extra dim might work

B4X:
ForEach lbl AsLabelIn pnlLabels.GetAllViewsRecursive
dim l as label
l=lbl
arrLabels(index)=l
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
then it's using 1 dim l as label at the start of the for each where it puts the actually label reference in.

and when you store that 10 times the last label will be referenced to when you use arrLabels(0) or arrLabels(66).

an extra dim might work

B4X:
ForEach lbl AsLabelIn pnlLabels.GetAllViewsRecursive
dim l as label
l=lbl
arrLabels(index)=l

If don't know if it works (I should test it) but when you set:
l = lbl

the reference shoud be the same


P.S. In fact, tested, it does not work
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
yes and no :)

sometimes in specific situations you need a new object to put the reference in.
otherwise you just overwrite the reference in the existing object.

not sure if this is one of these special cases tho but it seems like that.

maybe Erel can explain it better in detail.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The simplest solution is to use a List instead of an array and add the labels.

The reason for this issue is that Label is implemented as a wrapper. The variable lbl reuses the same wrapper while it iterates over the views and just changes the reference to the next label each time.

Examples that will work as you expect:
B4X:
For Each v As View In pnlLabels.GetAllViewsRecursive 'the type is View instead of Label
   lbls(i) = v
   lbls(i).Text = i
   i = i + 1
Next

B4X:
'This is the best option
Dim lbls As List
lbls.Initialize
For Each lbl As Label in pnlLabels.GetAllViewsRecursive
 lbls.Add(lbl)
Next
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
The reason for this issue is that Label is implemented as a wrapper. The variable lbl reuses the same wrapper while it iterates over the views and just changes the reference to the next label each time.

Understood :).

This thread was just to understand the "strange behavior"; as I wrote, using NumberOfViews and the code I posted there are no problems, as you know.


Thank you
 
Upvote 0
Top