Манипуляторы
Чтобы отделить логику событий от кода интерфейса, используйте для обработки событий манипулятор. Манипуляторы — это машины состояний, которые обрабатывают взаимодействие пользователя с элементами интерфейса. Они хранят, регистрируют и отменяют регистрацию обратных вызовов событий. Манипулятор упрощает настройку взаимодействия с пользователем, так что вам не нужно обрабатывать каждый обратный вызов по отдельности. Для обработки событий используйте один из манипуляторов, поддерживаемых UI Toolkit, или унаследуйтесь от него.
Чтобы создать и использовать манипулятор:
- Опишите отдельный класс, наследующий один из классов-манипуляторов, поддерживаемых UI Toolkit. Этот класс инкапсулирует логику обработки событий для конкретного взаимодействия с пользователем.
- Внутри класса реализуйте методы, реагирующие на нужные взаимодействия — щелчки мышью или перетаскивание. Эти методы получают и обрабатывают сведения, необходимые для выполнения желаемого поведения.
- Закончив проектировать класс манипулятора, создайте его экземпляр и прикрепите к целевому элементу интерфейса. Так манипулятор сможет перехватывать и обрабатывать нужные события, управляя взаимодействием с пользователем и оставаясь чётко отделённым от кода вашего интерфейса.
Поддерживаемые манипуляторы
В следующей таблице перечислены поддерживаемые классы манипуляторов:
| Манипулятор | Наследуется от | Описание |
|---|---|---|
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());
Дополнительные ресурсы
- Обработка событий
- Создание перетаскивания UI в окне пользовательского редактора
- Создание перетаскивания UI для перетаскивания между окнами Редактора
- 📺 Видео: UI Toolkit Серия уроков: Манипулятор перетаскивания