UG4L14——事件机制

本章代码关键字

1
2
eventContext.StopPropagation()        //打断事件的冒泡传递
eventContext.CaptureTouch() //按下后移动到对象外部抬起依然可以触发抬起

事件触发时的传递机制

举例说明:GRoot​——>面板——>A——>B——>C
当C触发一个事件时,比如TouchBegin​,该事件的触发会依次往上向父对象进行传递
C——>B——>A——>面板——>GRoot
它的事件触发的先后顺序也是如此,这种传递过程叫做冒泡传递机制

以面板右上角的按钮为例:

image

1
2
3
4
5
6
7
8
9
10
11
12
13
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
panel.m_btnTest.onTouchBegin.Add(() =>
{
print("按钮按下");
});
panel.onTouchBegin.Add(() =>
{
print("面板按下");
});
GRoot.inst.onTouchBegin.Add(() =>
{
print("GRoot按下");
});

输出:image

如果你想打断冒泡传递,可以通过 监听函数中的 EventContext​ 参数中的 StopPropagation​方法 进行打断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
panel.m_btnTest.onTouchBegin.Add((contextdata) =>
{
print("按钮按下");
contextdata.StopPropagation();
});
panel.onTouchBegin.Add(() =>
{
print("面板按下");
});
GRoot.inst.onTouchBegin.Add(() =>
{
print("GRoot按下");
});

输出:image

事件监听的两种委托

  • 无参委托 EventCallback0

    GObject​中所有的添加或者移除监听事件的方法(例如gObject.onClick.Add()​,匿名函数(lambda表达式)不能指定移除)
    都有使用无参委托EventCallback0​参数的重载,这种委托需要的监听方法是不需要参数的

    image

    image

    当监听方法不需要额外消息时,就可以使用该无参委托 EventCallback0​ 参数重载

    1
    2
    3
    4
    panel.onTouchBegin.Add(() =>
    {
    print("面板按下");
    });
  • 有参委托 EventCallback1

    GObject​中所有的添加或者移除监听事件的方法(例如gObject.onClick.Add()​,匿名函数(lambda表达式)不能指定移除)
    都有使用有参委托EventCallback1​参数的重载,这种委托需要的监听方法需要一个EventContext​参数

    image

    image

    1
    2
    3
    4
    5
    panel.m_btnTest.onTouchBegin.Add((contextdata) =>
    {
    print("按钮按下");
    contextdata.StopPropagation();
    });

有参委托的EventContext参数

  • sender​ 获得事件的分发者

    以gObject.onRollOver.Add()​为例

    如果想要获取进入了哪个元件,需要使用带EventContext​参数的委托,
    通过sender​属性去获取发生事件的元件,再转为GObject​去获取名字

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void Start()
    {
    TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>(
    panel.m_btnTest.onRollOver.Add(InObject);
    }

    private void InObject(EventContext eventData)
    {
    print("进入了某个对象" + (eventData.sender as GObject).name);
    }

    鼠标进入元件后输出:image

  • initiator​ 获得事件的发起者(DisplayObject原生对象)

  • type​ 事件类型

  • inputEvent​ 如果事件是键盘/触摸/鼠标事件,通过访问inputEvent对象可以获得这类事件的相关数据

    • x/y​ 鼠标或手指的位置(物理坐标,需要GRoot.inst.GlobalToLocal()​​转换)

      以gObject.onTouchMove.Add()​为例

      如果要得到鼠标移动的坐标,需要使用带EventContext​参数的委托,对传入的EventContext​参数通过inputEvent.x/y​得到移动位置

      注意!得到是物理屏幕坐标,如果想要使用UI坐标需要使用GlobalToLocal​进行一次转换

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
      panel.m_btnTest.onTouchBegin.Add((data) =>
      {
      print("按下");
      //如果想要获取鼠标哪个键按下:0左键 1右键 2中键
      print(data.inputEvent.button);
      });
      panel.m_btnTest.onTouchMove.Add((data) =>
      {
      print("移动");
      print(new Vector2(data.inputEvent.x, data.inputEvent.y));
      });

      在按下按钮时移动输出:image

    • keyCode​ 按键代码

      以Stage.inst.onKeyDown.Add()​举例

      获取键盘输入的是哪个键,需要使用带EventContext​参数的方法,通过inputEvent.keyCode​来获取

      1
      2
      3
      4
      Stage.inst.onKeyDown.Add((data) =>
      {
      print(data.inputEvent.keyCode);
      });

      按下按键时输出:image

    • mouseWheelDelta​ 鼠标滚轮滚动值

    • touchId​ 当前事件相关的手指ID

    • isDoubleClick​ 是否双击

  • data​ 事件的数据。根据事件不同,可以有不同的含义

  • StopPropagation​ 停止冒泡传递

    关于冒泡传递可见:eventContext.StopPropagation()​

    如果你想打断冒泡传递,可以通过 监听函数中的 EventContext​ 参数中的 StopPropagation​方法 进行打断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
    panel.m_btnTest.onTouchBegin.Add((contextdata) =>
    {
    print("按钮按下");
    contextdata.StopPropagation();
    });
    panel.onTouchBegin.Add(() =>
    {
    print("面板按下");
    });
    GRoot.inst.onTouchBegin.Add(() =>
    {
    print("GRoot按下");
    });

    输出:image

  • CaptureTouch​ 在 TouchBegin​ 调用该方法,可以让 TouchEnd​ 在对象外部也能触发

    按下后即使在UI控件外部抬起也能响应(按下后移动到外部,抬起还是能响应)(实际上,即使不手动调用该方法,按下后移动到外部,抬起还是可以响应,原理不明)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
    panel.m_btnTest.onTouchBegin.Add((data) =>
    {
    print("按下");
    //如果想要获取鼠标哪个键按下:0左键 1右键 2中键
    print(data.inputEvent.button);
    //按下后即使在UI控件外部抬起也能响应
    data.CaptureTouch();
    });

    panel.m_btnTest.onTouchEnd.Add((data) =>
    {
    print("抬起");
    });
  • UncaptureTouch​ 取消​CaptureTouch(该方法未找到定义,原因不明)​发起的触摸事件捕获(该方法未找到定义,原因不明)