Snap-To Grid

Kevin

Well-Known Member
Licensed User
Longtime User
I'm adding drag & drop functionality to my app using Erel's class sample.

I'd like to implement a snap-to grid so that the views somewhat align themselves. For example, a virtual grid line every 5dip horizontally and vertically.

I'm sure I can figure it out, but my solutions sometimes tend to be more complicated than they need to be. So I'm curious if anyone has already done something like this or has an idea on how to incorporate that into the code in Erel's sample.

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
    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
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Here:
B4X:
Sub Class_Globals
   Private innerView As View
   Private panel1 As Panel
   Private downx, downy As Int
   Private ACTION_DOWN As Int
   Public GridX = 20dip, GridY = 20dip As Int
End Sub

Sub Initialize(Activity As Activity, v As View)
   innerView = v
   panel1.Initialize("")
   panel1.Color = Colors.Transparent
   Activity.AddView(panel1, v.Left, v.Top, v.Width, v.Height)
   ACTION_DOWN = Activity.ACTION_DOWN
   Dim r As Reflector
   r.Target = panel1
   r.SetOnTouchListener("Panel1_Touch")
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 
      Dim l As Int = innerView.Left + x - downx
      Dim t As Int = innerView.Top + y - downy
      innerView.Left = l - (l Mod GridX)
      innerView.Top = t - (t Mod GridY)
      panel1.Left = innerView.Left
      panel1.Top = innerView.Top
   End If
   Return True
End Sub
 
Upvote 0

Kevin

Well-Known Member
Licensed User
Longtime User
Well, I'm glad I asked because that was sooooooo much easier than I was thinking. I'm a "hack"! :eek:

As always... thank you!

I may as well ask this now: What's the easiest way to add long-press events to the draggable views? I'm thinking I need to use a timer and compare starting and ending coordinates and if they are close to the same, assume a long-press? Only problem with that is if the user is just trying to move the view a tiny bit, it may trigger the long-press. Although a snap grid may prevent that.
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You should add a global boolean value named ViewMoved:
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
  ViewMoved = False
  DownTime = DateTime.Now 'a global Long variable
    Else If Action = ACTION_MOVE Then 
        Dim l As Int = innerView.Left + x - downx
        Dim t As Int = innerView.Top + y - downy
        innerView.Left = l - (l Mod GridX)
        innerView.Top = t - (t Mod GridY)
        if ViewMoved = False And (panel1.Left <> innerView.Left OR panel1.Top <> innerView.Top) Then
  ViewMoved = True
End If
        panel1.Left = innerView.Left
        panel1.Top = innerView.Top
    Else If Action = ACTION_UP Then
      If ViewMoved = False AND DateTime.Now - DownTime > 50 Then
        'Raise LongPressed event
      End If
    End If
    Return True
End Sub
 
Upvote 0
Top