To create a moveable BubbleView, @Brandsum 's inspiration made a promising test project possible.
The solution is far from optimal, but almost fulfills its purpose (2), since the pointer follows the view movements (3).
Unfortunately the canvas-drawn "pointer triangle" is covered (4) by other views on the parent panel (SendToBack didn't help).
As there is no experience how to work with canvas so far, a push in the right direction is needed.
The solution is far from optimal, but almost fulfills its purpose (2), since the pointer follows the view movements (3).
B4X:
' -------------------------------------
' Class draggablebubble
' -------------------------------------
'
' Inspired by Erel --> https://www.b4x.com/android/forum/threads/classes-are-soon-coming.18395/
'
'***************************
' Usage example
'***************************
'Sub Activity_Create(FirstTime As Boolean)
' Activity.LoadLayout("1")
' Dim dv1 As draggableview
' dv1.Initialize(MainBackPanel, Label1, Label0, 0xff06AF8F)
'End Sub
'***************************
Sub Class_Globals
Private innerView As B4XView
Private TouchPanelOverBubble As Panel
Private downx As Int
Private downy As Int
Private ACTION_DOWN, ACTION_MOVE, ACTION_UP As Int
Private cvs As B4XCanvas
Private av As B4XView
Private panX As Panel
Private bcolor As Int
Private shadowwidth As Int = 2dip
End Sub
Sub Initialize(ParentPanel As Panel, ViewToBlubble As B4XView, AnchorView As View, BackColor As Int)
panX = ParentPanel
av = AnchorView
bcolor = BackColor
cvs.Initialize(panX)
innerView = ViewToBlubble
TouchPanelOverBubble.Initialize("")
TouchPanelOverBubble.Color = Colors.Transparent
ViewToBlubble.SetColorAndBorder(bcolor, 0, 0, 5dip)
panX.AddView(TouchPanelOverBubble, ViewToBlubble.Left, ViewToBlubble.Top, ViewToBlubble.Width, ViewToBlubble.Height)
ACTION_DOWN = panX.ACTION_DOWN
ACTION_MOVE = panX.ACTION_MOVE
ACTION_UP = panX.ACTION_UP
Dim r As Reflector
r.Target = TouchPanelOverBubble
r.SetOnTouchListener("Panel1_Touch") 'why reflection instead of the regular Panel_Touch event? Good question which deserves a forum thread of its own (not related to classes)...
BubbleMoved
End Sub
Private Sub Panel1_Touch (o As Object, ACTION As Int, x As Float, y As Float, motion As Object) As Boolean
If ACTION = ACTION_DOWN Then
downx = x
downy = y
Else
innerView.Left = innerView.Left + x - downx
innerView.Top = innerView.Top + y - downy
TouchPanelOverBubble.Left = innerView.Left
TouchPanelOverBubble.Top = innerView.Top
BubbleMoved
End If
Return True
End Sub
private Sub BubbleMoved
cvs.ClearRect(cvs.TargetRect)
' --- Draw shadow for inner view
Dim l,t,r,b As Float
l = innerView.Left
t = innerView.Top +shadowwidth
r = innerView.Left + innerView.Width
b = innerView.Top + innerView.Height +shadowwidth
Dim ivrec As B4XRect
ivrec.Initialize(l,t,r,b)
Dim path As B4XPath
path.InitializeRoundedRect(ivrec, 5dip)
cvs.ClipPath(path)
cvs.DrawRect(cvs.TargetRect, Colors.ARGB(3* 24, 160, 160, 160) , True, shadowwidth)
cvs.RemoveClip
' --- Draw shadow for pointer
For i = 0 To 3
Dim bpa As B4XPath
bpa.Initialize(innerView.Left +(innerView.Width/2), innerView.Top +(innerView.Height /2))
bpa.LineTo( av.Left +(av.Height /2), av.Top + (av.Height /2) )
bpa.LineTo( innerView.Left +(innerView.Width/2), innerView.Top +(innerView.Height /2) +24dip + i*shadowwidth)
cvs.DrawPath(bpa, Colors.ARGB(i*24, 160, 160, 160), True, 0)
Next
' --- Draw pointer
Dim bpa As B4XPath
bpa.Initialize(innerView.Left +(innerView.Width/2), innerView.Top +(innerView.Height /2))
bpa.LineTo( av.Left +(av.Height /2), av.Top + (av.Height /2))
bpa.LineTo( innerView.Left +(innerView.Width/2), innerView.Top +(innerView.Height /2) +24dip)
cvs.DrawPath(bpa, bcolor, True, 0)
panX.Invalidate ' Is this needed?
End Sub
' -----------------------------
' Main activity
' -----------------------------
#Region Project Attributes
#ApplicationLabel: B4A Example
#VersionCode: 3
#VersionName:
'SupportedOrientations possible values: unspecified, landscape or portrait.
#SupportedOrientations: unspecified
#CanInstallToExternalStorage: False
#End Region
#Region Activity Attributes
#FullScreen: False
#IncludeTitle: True
#End Region
Sub Process_Globals
Private su As StringUtils
End Sub
Sub Globals
Private MainBackPanel As B4XView
Private Label0 As B4XView
Private Label1 As B4XView
Private Label2 As B4XView
Private Label3 As B4XView
Private dv1 As draggablebubble
Private BubbleAnkerView As String = ""
End Sub
Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("Layout1")
Activity.Color = Colors.White
Label0.SetColorAndBorder(0xff425CFB, 0, 0, Label0.Width / 2)
Label1.Text = "Drag me around. Lorem ipsum dolor sit amet, consectetuer adipiscing elit."
Label1.Width = 200dip
Label1.Height = su.MeasureMultilineTextHeight(Label1, Label1.Text)
Label2.Text = "..."
BubbleAnkerView = "Label0"
dv1.Initialize(MainBackPanel, Label1, Label0, 0xff06AF8F)
End Sub
Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub Label3_Click
If BubbleAnkerView = "Label0" Then
Label1.Text = "Go ahead - drag again. Aenean commodo ligula eget dolor. Aenean massa."
dv1.Initialize(MainBackPanel, Label1, Label3, 0xff06AF8F)
BubbleAnkerView = "Label3"
Else
Label1.Text = "And the drag goes on. Lorem ipsum dolor sit amet, consectetuer adipiscing elit."
dv1.Initialize(MainBackPanel, Label1, Label0, 0xffFC4242)
BubbleAnkerView = "Label0"
End If
Label2.Text = "BubbleAnkerView = " & BubbleAnkerView
End Sub
Unfortunately the canvas-drawn "pointer triangle" is covered (4) by other views on the parent panel (SendToBack didn't help).