Drag button around screen

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
I am starting a project that will eventually involve dragging buttons displaying numbers around the screen.

Can anyone point me in the right direction?

My first thoughts are to use a button to hold the number (which is displayed in the text) instead of some other view simply because it seems the most direct.

I am tending toward the Gestures library to detect finger movements around the screen.

I will make the button the child of a panel covering most of the screen which the button can be dragged around.

I will use the button down and up events and the gesture movement events to implement dragging the button.

Does this sound reasonable? Is there a better approach or better view object to use? Can anyone point me to a tutorial or example?

Thanks much,
Barry.
 

dagnabitboy

Active Member
Licensed User
Longtime User
Here is the first gestures program I wrote.. very crude.. it puts a label on the screen. You can touch anywhere on the screen and move your finger.. the label moves the same amount and direction you move your finger.
 

Attachments

  • touch001.zip
    6 KB · Views: 733
Upvote 0

canalrun

Well-Known Member
Licensed User
Longtime User
Here is the first gestures program I wrote.. very crude.. it puts a label on the screen. You can touch anywhere on the screen and move your finger.. the label moves the same amount and direction you move your finger.

Thanks a million. This looks excellent.

Barry.
 
Upvote 0

jlam

Member
Licensed User
Longtime User
multiple buttons

I would like to use gesture and modify toucho1. The app will have 5 buttons. How do I know which button has been selected and dragged.?
Thanks:sign0085:
 
Upvote 0

tamadon

Active Member
Licensed User
Longtime User
Search the forums for "Sender".

I am writing an app with similar requirement.

I want to be able to drag the button on Button_Down event. Here I set the panel.BringToFront but the panel_Gesture does not even fire.

What's the proper way to select a button from a group and drag it right away since we are actually touching/dragging on the panel and not the button.
 
Upvote 0

tamadon

Active Member
Licensed User
Longtime User
Thanks Erel, that helps a lot.

My next question is, how do you determine which view is being clicked? I am using button view but the click event is not raised when the class is used.

So I tried modifying the class to detect the click event in the Private Sub Panel1_Touch but a bit stuck here. How do I access the individual button's tag value? Currently it returns null as in the following code that I added to the DraggableView class

B4X:
Private Sub whichButton

   innerView = Sender
   
   btnIndex = innerView.Tag 'btnIndex is the x.y index of the button
   
   For x = 0 To 2
      For y = 0 To 2
         If btnIndex.x = x AND btnIndex.y = y Then
            Log(x & ":" & y) 
         End If
      Next
   Next

End Sub

I've modified the initialize sub to the following

B4X:
Sub Initialize(Activity As Activity, v As View, Index As Indices)
    innerView = v
   innerView.Tag = Index
    panel1.Initialize("")
    panel1.Color = Colors.Transparent
   Activity.AddView(panel1, v.Left, v.Top, v.Width, v.Height)
    ACTION_DOWN = Activity.ACTION_DOWN
    ACTION_MOVE = Activity.ACTION_MOVE
    ACTION_UP = Activity.ACTION_UP
    Dim r As Reflector
    r.Target = panel1
    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)...
End Sub
 
Upvote 0

tamadon

Active Member
Licensed User
Longtime User
Thanks Erel. But can you explain how do I do that if I have several buttons? How do I create an array of class field to store and then retrieve the information?
 
Upvote 0

tamadon

Active Member
Licensed User
Longtime User
Hi Erel,

One of the values I want to store in the class field is a bitmap. However it appears that all of the objects' bitmap is set to the last bitmap instead of each unique bitmap set during an iteration in the main sub during initialization.

For instance in the Initialize sub of the DraggableView class I modified it to

B4X:
Sub Initialize(Activity As Activity, v As View, tag As Int, diceImg As Bitmap)
    innerView = v
   bMap = diceImg
   bTag  = tag
    panel1.Initialize("")
    panel1.Color = Colors.Transparent
   Activity.AddView(panel1, v.Left, v.Top, v.Width, v.Height)
    ACTION_DOWN = Activity.ACTION_DOWN
    ACTION_MOVE = Activity.ACTION_MOVE
    ACTION_UP = Activity.ACTION_UP
    Dim r As Reflector
    r.Target = panel1
    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)...
   
End Sub

To trap the click event I modified the Panel1_Touch sub to which raises the insertPanelImage event

B4X:
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
      Log("On click: " & bMap)
      CallSub3(Me, "insertPanelImage", bTag, bMap)
    Else 
        innerView.Left = innerView.Left + x - downx
        innerView.Top = innerView.Top + y - downy        
        panel1.Left = innerView.Left
        panel1.Top = innerView.Top
    End If
    Return True
End Sub


B4X:
Sub insertPanelImage(btnTag As Int, btnMap As Bitmap)
   Log("On insertPanelImage: " & btnMap)
   CallSub3(Main, "updatePanelIcon", btnTag, btnMap)
   CallSub2(Main, "ChangePanel", btnTag)
End Sub

the btnTag carries the correct unique values for the object but btnMap seems to carry the same bitmap.

What am I doing wrong?

Also I am sure there's a more elegant way to use CallSub2 to raise the event instead of using several CallSub2,3 from the Main module.. Anyway if there's a suggestion to simplify it I would appreciate to know. Thanks for the help..
 
Upvote 0

tamadon

Active Member
Licensed User
Longtime User
Here it is

B4X:
Sub drawBtnDice
   Dim i, j, x, y, rndDice(9) As Int
   Dim bufferIcon() As Byte
   Dim bmpIcon As Bitmap

   For i = 0 To 8
      rndDice(i) = i
   Next   
   storyClass.ShuffleArray(rndDice)
   
   
   Dim dv(9) As DraggableView   

   For y = 0 To 2
      For x = 0 To 2
         
         Dim b As Button
         
         b.Initialize("") 'No event name added because draggable views event will not be raised
         Activity.AddView(b,offsetX + x * (btnWidth + 15dip), offsetY + y * (btnWidth + 1dip), btnWidth, btnWidth)
         btnDice(x, y) = b 'store a reference to this view
         
         'We have 9 dices and each dice can have one of the six possible icons
         rndNumber2 = Rnd(0, 6)

         cursorStory = sqlStory.ExecQuery("SELECT * FROM story WHERE rowid=" & iconID(rndDice(j), rndNumber2))      
         cursorStory.Position = 0
         bufferIcon = cursorStory.GetBlob("icon")
         cursorStory.Close
      
         Dim iconIS As InputStream
      
         iconIS.InitializeFromBytesArray(bufferIcon, 0, bufferIcon.Length)
         bmpIcon.Initialize2(iconIS)
         iconIS.Close
         
         'Initialize draggable view
         dv(j).Initialize(Activity, b, j, bmpIcon)
         
         'Initialize animation scale center
         diceAnim(x, y).InitializeScaleCenter("", 0, 0, 1, 1, b)
         
         'Set animation length
         diceAnim(x, y).Duration = 500
         
         diceAnim(x, y).start(btnDice(x, y))
         'btnDice(x, y).Visible = True
         btnDice(x, y).SetBackgroundImage(bmpIcon)
         
         'Play sound
         sndPPop(j) = SP.Play(sndLPop(j), 1, 1, 1, 0, 1)
         storyClass.Wait(j)
         j = j + 1
      Next
   Next
   
   

End Sub
 
Upvote 0
Top