Unity 6.3
0 онлайн 101 гостей 3 в системе
Вход
UI системы Шаг 175 из 317

Манипуляторы

Чтобы отделить логику событий от кода интерфейса, используйте для обработки событий манипулятор. Манипуляторы — это машины состояний, которые обрабатывают взаимодействие пользователя с элементами интерфейса. Они хранят, регистрируют и отменяют регистрацию обратных вызовов событий. Манипулятор упрощает настройку взаимодействия с пользователем, так что вам не нужно обрабатывать каждый обратный вызов по отдельности. Для обработки событий используйте один из манипуляторов, поддерживаемых UI Toolkit, или унаследуйтесь от него.

Чтобы создать и использовать манипулятор:

  1. Опишите отдельный класс, наследующий один из классов-манипуляторов, поддерживаемых UI Toolkit. Этот класс инкапсулирует логику обработки событий для конкретного взаимодействия с пользователем.
  2. Внутри класса реализуйте методы, реагирующие на нужные взаимодействия — щелчки мышью или перетаскивание. Эти методы получают и обрабатывают сведения, необходимые для выполнения желаемого поведения.
  3. Закончив проектировать класс манипулятора, создайте его экземпляр и прикрепите к целевому элементу интерфейса. Так манипулятор сможет перехватывать и обрабатывать нужные события, управляя взаимодействием с пользователем и оставаясь чётко отделённым от кода вашего интерфейса.

Поддерживаемые манипуляторы

В следующей таблице перечислены поддерживаемые классы манипуляторов:

Манипулятор Наследуется от Описание
Manipulator Базовый класс для всех предоставляемых манипуляторов.
KeyboardNavigationManipulator Manipulator Обрабатывает преобразование событий ввода для конкретного устройства в операции навигации более высокого уровня с помощью клавиатуры.
MouseManipulator Manipulator Обрабатывает ввод мыши. Имеет список фильтров активации.
ContextualMenuManipulator MouseManipulator Отображает контекстное меню при щелчке правой кнопкой мыши или нажатии клавиши меню на клавиатуре.
PointerManipulator MouseManipulator Обрабатывает ввод указателя. Имеет список фильтров активации.
Clickable PointerManipulator Отслеживает события мыши на элементе и определяет, когда происходит щелчок, который является одновременно нажатием указателя и его освобождением на одном и том же элементе.

Примеры

Следующие примеры демонстрируют, как использовать манипуляторы для обработки событий. Они выполняют следующие действия:

  • Наследовать манипуляторы от PointerManipulators класс, который обрабатывает ввод мыши.
  • Используйте список activators для указания условий, которые активируют манипулятор. Например, чтобы активировать манипулятор при нажатии пользователем левой кнопки мыши, добавьте ManipulatorActivationFilter в список activators с полем button установленным на MouseButton.LeftMouse.
  • Используйте свойство target для доступа к элементу, к которому прикреплен манипулятор.
  • Переопределяет методы RegisterCallbacksOnTarget и UnregisterCallbacksFromTarget для регистрации и отмены регистрации обратных вызовов событий.

Создание манипулятора ExampleDragger

В следующем примере создается манипулятор, который перемещает элемент при нажатии и перетаскивании:

using UnityEngine;
using UnityEngine.UIElements;

public class ExampleDragger : PointerManipulator
{
    private Vector3 m_Start;
    protected bool m_Active;
    private int m_PointerId;
    private Vector2 m_StartSize;

    public ExampleDragger()
    {
        m_PointerId = -1;
        activators.Add(new ManipulatorActivationFilter { button = MouseButton.LeftMouse });
        m_Active = false;
    }

    protected override void RegisterCallbacksOnTarget()
    {
        target.RegisterCallback<PointerDownEvent>(OnPointerDown);
        target.RegisterCallback<PointerMoveEvent>(OnPointerMove);
        target.RegisterCallback<PointerUpEvent>(OnPointerUp);
    }

    protected override void UnregisterCallbacksFromTarget()
    {
        target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
        target.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
        target.UnregisterCallback<PointerUpEvent>(OnPointerUp);
    }

    protected void OnPointerDown(PointerDownEvent e)
    {
        if (m_Active)
        {
            e.StopImmediatePropagation();
            return;
        }

        if (CanStartManipulation(e))
        {
            m_Start = e.localPosition;
            m_PointerId = e.pointerId;

            m_Active = true;
            target.CapturePointer(m_PointerId);
            e.StopPropagation();
        }
    }

    protected void OnPointerMove(PointerMoveEvent e)
    {
        if (!m_Active || !target.HasPointerCapture(m_PointerId))
            return;

        Vector2 diff = e.localPosition - m_Start;

        target.style.top = target.layout.y + diff.y;
        target.style.left = target.layout.x + diff.x;

        e.StopPropagation();
    }

    protected void OnPointerUp(PointerUpEvent e)
    {
        if (!m_Active || !target.HasPointerCapture(m_PointerId) || !CanStopManipulation(e))
            return;

        m_Active = false;
        target.ReleaseMouse();
        e.StopPropagation();
    }
}

Создание манипулятора ExampleResizer

В следующем примере создается манипулятор, который изменяет размер элемента при его перетаскивании:

using UnityEngine;
using UnityEngine.UIElements;

public class ExampleResizer : PointerManipulator
{
    private Vector3 m_Start;
    protected bool m_Active;
    private int m_PointerId;
    private Vector2 m_StartSize;
    public ExampleResizer()
    {
        m_PointerId = -1;
        activators.Add(new ManipulatorActivationFilter { button = MouseButton.LeftMouse });
        m_Active = false;
    }

    protected override void RegisterCallbacksOnTarget()
    {
        target.RegisterCallback<PointerDownEvent>(OnPointerDown);
        target.RegisterCallback<PointerMoveEvent>(OnPointerMove);
        target.RegisterCallback<PointerUpEvent>(OnPointerUp);
    }

    protected override void UnregisterCallbacksFromTarget()
    {
        target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
        target.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
        target.UnregisterCallback<PointerUpEvent>(OnPointerUp);
    }

    protected void OnPointerDown(PointerDownEvent e)
    {
        if (m_Active)
        {
            e.StopImmediatePropagation();
            return;
        }

        if (CanStartManipulation(e))
        {
            m_Start = e.localPosition;
            m_StartSize = target.layout.size;
            m_PointerId = e.pointerId;
            m_Active = true;
            target.CapturePointer(m_PointerId);
            e.StopPropagation();
        }
    }

    protected void OnPointerMove(PointerMoveEvent e)
    {
        if (!m_Active || !target.HasPointerCapture(m_PointerId))
            return;

        Vector2 diff = e.localPosition - m_Start;

        target.style.height = m_StartSize.y + diff.y;
        target.style.width = m_StartSize.x + diff.x;

        e.StopPropagation();
    }

    protected void OnPointerUp(PointerUpEvent e)
    {
        if (!m_Active || !target.HasPointerCapture(m_PointerId) || !CanStopManipulation(e))
            return;

        m_Active = false;
        target.ReleasePointer(m_PointerId);
        m_PointerId = -1;
        e.StopPropagation();
    }
}

Добавление или удаление манипулятора

Чтобы добавить манипулятор к элементу, используйте метод AddManipulator. Чтобы удалить манипулятор из элемента, используйте метод RemoveManipulator.

В следующем примере ExampleDragger добавляется и удаляется из VisualElement:

// Create a VisualElement.
var myElement = new VisualElement();
var dragger = new ExampleDragger();

// Add manipulators to the VisualElement.
myElement.AddManipulator(dragger);

// Remove manipulators from the VisualElement.
myElement.RemoveManipulator(dragger);

В следующем примере ExampleResizer добавляется к VisualElement:

var box = new VisualElement()
{
    style =
    {
        left = 100,
        top = 100,
        width = 100,
        height = 100,
        backgroundColor = Color.red
    },
    pickingMode = PickingMode.Position,
};

box.AddManipulator(new ExampleResizer());

Дополнительные ресурсы