I'm trying to calculate the cumulative position of a view inside a scrollview (or the activity, if there is no scrollview involved) - that is, the left and top offsets of the view and all its parent views up to the base container.
So, I'm getting the left and top coordinates of the view, it's parent view (e.g. a panel), the grandparent's view (e.g. another panel), until I hit the base container (e.g. a scrollview or the activity).
However, when I try to get the Left of a panel, I get a classCastException:
Panels have a Left property, so why am I getting this exception?
Here's my code:
BTW, when I pass a view such as a spinner to this sub, the spinner (assigned to tempView) causes the "is Panel" expression to return TRUE. Is this because all views are internally based on panels? Is there a way to test if a view is actually a panel (in the B4A user's sense)?
Also BTW, I know that, for an activity with no scrollview, I can easily get this result using getLocationonScreen. However, I also need to handle the case where the view's ancestor is a scrollview, so I wanted to create a single method that would handle both. But I'm happy to hear about other solutions too.
Any help greatly appreciated. This one is boggling me...
So, I'm getting the left and top coordinates of the view, it's parent view (e.g. a panel), the grandparent's view (e.g. another panel), until I hit the base container (e.g. a scrollview or the activity).
However, when I try to get the Left of a panel, I get a classCastException:
B4X:
java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to anywheresoftware.b4a.BALayout$LayoutParams
at anywheresoftware.b4a.objects.ViewWrapper.getLeft(ViewWrapper.java:150)
...
Panels have a Left property, so why am I getting this exception?
Here's my code:
B4X:
'Calculate the position of the view relative to its base container (scrollview if any, otherwise activity)
'Returns an integer array where index 0 is left, index 1 is top
public Sub getCumulativePosition(viewArg As View) As Int()
Dim tempLeft, tempTop As Int
Dim tempView As View = viewArg
Dim parentView As View = viewArg.Parent
Do While True
If tempView Is Panel Then 'a spinner tests as TRUE here (because it's based on a panel internally?)
Dim tempPanel As Panel = tempView 'try an explicit cast to avoid classCast exception
tempLeft = tempLeft + tempPanel.Left 'exception raised - cannot cast to BALayout
tempTop = tempTop + tempPanel.Top
Else
tempLeft = tempLeft + tempView.Left
tempTop = tempTop + tempView.Top
End If
If (parentView Is ScrollView) Or (parentView = tipActivity) Then Exit
tempView = parentView
parentView = parentView.Parent
Loop
If parentView = tipActivity Then
tempTop = tempTop - (GetDeviceLayoutValues.Height - tipActivity.Height) 'adjust for title bar, if any
End If
Return Array As Int(tempLeft, tempTop)
End Sub
BTW, when I pass a view such as a spinner to this sub, the spinner (assigned to tempView) causes the "is Panel" expression to return TRUE. Is this because all views are internally based on panels? Is there a way to test if a view is actually a panel (in the B4A user's sense)?
Also BTW, I know that, for an activity with no scrollview, I can easily get this result using getLocationonScreen. However, I also need to handle the case where the view's ancestor is a scrollview, so I wanted to create a single method that would handle both. But I'm happy to hear about other solutions too.
Any help greatly appreciated. This one is boggling me...
Last edited: