6
\$\begingroup\$

I am trying to recreate a UI menu that has functionality similar to the iPhone's home screen:

  • If a user drags anywhere on the menu (including on a button), it should drag the whole page left/right depending on the user's drag.
  • If a user clicks and holds motionlessly on a single button, it "dislodges" the button so that it can be dragged around.

alt text

I have all of my functionality working, including the dislodge. The one exception being that I'm running into a situation where I'm not sure how to transfer the drag message consumed by a button onto the backing scroll container if the user has not clicked long enough on a single button to "dislodge" it.

That is, I place my finger onto a button and drag (with the intention of dragging the entire page) but I'm not sure how to redirect the same drag message onto the ScrollRect of my backing container. Instead, my button consumes the OnDrag message and the page is not scrolled. The only method of scrolling the page is simply dragging on an empty part of the container where there is no button.

alt text

I'm using UI elements from Unity's 4.6 UI:

  • I am using a ScrollRect to represent the backing container with all of my buttons

  • I'm using a GridLayout to resize and pad my buttons

  • I'm using a regular UI.Button class on each of my buttons

  • I'm using the following EventSystem interfaces to catch and handle input for my buttons: IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler

Is there something already built into Unity that can allow me to transfer/redirect the drag message from one GameObject to another while the drag is still in process? Or do I need to rebuild parts of the UI from scratch to support this?

\$\endgroup\$
1
\$\begingroup\$

What you can do from the OnDrag implementation of the button is this.

public void OnDrag(PointerEventData eventData)
    {
        if(scroll)// scroll is the GameObject with the ScrollRect component you will have to ckeck for the different drags here.
        {
            scroll.SendMessage("OnDrag", eventData);//This passes the drag message that started from the button onto the ScrollRect but it results in some jittery motion maybe you will have to modify eventData.
        }
    }

After a quick test the jittery motion is only when the movement type is elastic but giving it a higher elasticity fixed the problem.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

This is something I did in UnityScript, you can adapt it accordingly.

This uses the mouse to drag.

You need to add an EventTrigger component to your button. Then add a PointerDown, PointerUp and a Drag event. Drag your GameObject where the script lies onto each event and then find the relevant function for each:

StopDragging function to PointerUp AttemptingDrag to PointerDown Dragging to Drag

#pragma strict


var MouseCoord : Vector2;

var ObjectToDrag : GameObject;

var NextClickTime = 0.0;
var NextClickInterval = 1;

var Drag : boolean;
var DragBackground : boolean;

var TransformChanged : boolean; 


function Start () {

}

function Update () {

  if (Drag && (Time.time > NextClickTime) && (!ObjectToDrag.transform.hasChanged)) 
  // If we want to move the background and the button has not been dragged!
  {
    Drag = false;
    DragBackground = true;  // We now shift focus to the background. 
  }  


  if (DragBackground) // If we want to move the background 
  {

    ObjectToDrag = GameObject.Find("ShoppingBackground"); 
                              // Find the background. 


    ObjectToDrag.transform.localPosition.y  = MouseCoord.y;

    // The background will move with the mouse.
    ObjectToDrag.transform.position.x = MouseCoord.x; 
  }  


  //If you want to see the mouse coordinates in the inspector.
  MouseCoord.x = Input.mousePosition.x;
  MouseCoord.y = Input.mousePosition.y;
}


function Dragging()
{
  print ("Hit Button");


  if (Drag) 
  {
    ObjectToDrag.transform.hasChanged = true; 

    // We tell the computer that the object is in fact being dragged. 
    TransformChanged = ObjectToDrag.transform.hasChanged; 
    // We show this fact in the inspector.   

    // The button will move with the mouse.
    ObjectToDrag.transform.position.y = MouseCoord.y; 
    ObjectToDrag.transform.position.x = MouseCoord.x; 

  }

}


function StopDragging() 
{
  Drag = false; 
  DragBackground = false; 
}

function AttemptingDrag() 
{
  NextClickTime = Time.time + NextClickInterval; 
  // If we stay still interval is now set. 
  Drag = true; 


  if (Drag) // If we are merely dragging the button
  { 
    // Find the button to grab.
    ObjectToDrag  = GameObject.Find("RemoteControlSpiderButton");  


    // We tell the computer that the Button has not changed position.
    ObjectToDrag.transform.hasChanged = false;
    // We show this fact in the inspector. 
    TransformChanged = ObjectToDrag.transform.hasChanged;
  }    
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.