# 如何解决地图页面操作手势卡顿或者不生效

#### 问题现象

在应用内使用地图功能时，地图页面操作手势卡顿或者不生效。

#### 背景知识

*   多层级手势事件：多层级手势事件指父子组件嵌套时，父子组件均绑定了手势或事件。在该场景下，手势或者事件的响应受到多个因素的影响，相互之间发生传递和竞争，容易出现预期外的响应。
    1.  触摸事件（onTouch事件）：是所有手势组成的基础，有Down，Move，Up，Cancel四种。手势均由触摸事件组成，例如点击为Down+Up，滑动为Down+一系列Move+Up。
        *   触摸热区设置和触摸测试控制可以控制Touch事件的分发，从而可以影响到onTouch事件和手势的响应。而绑定手势方法属性可以控制手势的竞争从而影响手势的响应，但不能影响到onTouch事件。
            
            触摸测试流程从根节点开始遍历，默认按照UI的Z序由子节点开始收集事件响应链（决定组件的响应顺序），触摸事件（onTouch事件）是冒泡事件默认会向上一直传递下去，直到被消费或者丢弃，允许多个组件同时触发。
            
        *   事件响应链：ArkUI事件响应链收集，根据右子树（按组件布局的先后层级）优先的后序遍历流程。响应链举例，按下图的组件树，hitTestBehavior属性均为默认，用户点按的动作如果发生在组件E上，则最终收集到的响应链，以及先后关系是E->D->A。因为组件D的hitTestBehavior属性为default，收集到事件后会阻塞兄弟节点，所以没有收集组件B的左子树，存在遮盖关系。
            
    2.  手势与事件响应及优先级：除了触摸事件（onTouch事件）外的所有手势与事件，均是通过基础手势或者组合手势实现的。在默认情况下，这些手势为非冒泡事件，除非显式声明允许多个手势同时成功，同一时间只会有一个手势响应。
        
        *   系统手势：系统控件默认实现的手势（系统内置手势），调用某些通用事件内置的手势，比如拖拽，click，一些控件内包手势，比如bindmenu内包点击，bindcontextmenu内包长按。
        *   自定义手势：通过绑定手势API，如使用gesture声明的事件回调。参考绑定手势方法。
        
        *   当父子组件均绑定同一类手势时，子组件优先于父组件触发。
        *   当一个组件同时绑定多个手势时，先达到手势触发条件的手势优先触发。
        *   同一组件绑定相同事件类型的隐式手势和显式手势时，隐式手势会优先响应。比如显式手势TapGesture和隐式手势onClick，只会响应onClick事件。
        
    3.  自定义控制的多层级手势事件：可以通过设置属性，控制默认的多层级手势事件竞争流程，更好的实现手势事件。
*   单一手势：包括点击手势（TapGesture）、长按手势（LongPressGesture）、拖动手势（PanGesture）、捏合手势（PinchGesture）、旋转手势（RotationGesture）和滑动手势（SwipeGesture）六种。
*   组合手势：组合手势由多种单一手势组合而成，通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型，支持顺序识别、并行识别和互斥识别三种类型。
*   绑定手势方法：通过给各个组件绑定不同的手势事件，并设计事件的响应方式，当手势识别成功时，ArkUI框架将通过事件回调通知组件手势识别的结果。
*   事件独占控制：设置组件是否独占事件，事件范围包括组件自带的事件和开发者自定义的点击、触摸、手势事件。
*   手势冲突处理：手势冲突是指多个手势识别器在同一组件或重叠区域同时识别时产生竞争，导致识别结果不符合预期。常见冲突场景包括：
    
    1.  同一组件上的多手势（如按钮同时添加点击与长按手势）。
    2.  父子组件的同类型手势识别器。
    3.  系统默认手势与自定义手势（如scroll滑动手势与子组件点击手势冲突）。
    
    干预手势处理可有效解决冲突，除控制组件响应热区和命中测试模式外，主要通过以下三种方式：自定义手势判定、手势并行动态控制、阻止手势参与识别。
    

#### 解决方案

*   地图组件上层存在遮盖的组件。对地图组件上层组件做手势穿透，和触摸事件一样，手势事件也可以通过hitTestBehavior属性来进行透传，参考触摸测试控制。
*   地图组件和其他组件存在手势冲突。
    1.  Grid、List、Scroll、Swiper、WaterFlow等滚动容器的嵌套，可以尝试使用nestedScroll属性来解决视图滚动冲突的问题。
    2.  对于单个组件组合手势的使用产生的冲突，以及自定义手势和系统手势冲突，可以尝试使用组合手势中的顺序识别、并行识别和互斥识别来解决。
    3.  对于多层组件手势响应冲突，可以参考多层级手势事件。
    4.  如果只是需要动态控制自定义手势是否响应，参考自定义手势判定。
    5.  对于多点触控产生的手势冲突，参考事件独占控制。