关于高德标注点气泡不能点击与hitTest:withEvent:方法详解

       前言

        最近App增加新功能,需要在高德地图上进行点击标注并增加气泡。气泡二次点击进行导航。按照文档集成后,把imageView改成button。结果发现无法处理点击事件。经过分析,应该是气泡是基于标注添加的。而标注在地图中范围特别小,气泡的范围超出了标注的范围。众所周知,超过父视图范围的button是不能响应点击事件的。

       解决原理

         解决这个问题,首先想到了hitText: withEvent:方法。下面具体说一下hitText: 

withEvent方法使用。iOS系统检测到Touch操作时会将其放入当前活动Application的事件队

列,Application会从事件队列中取出触摸事件并传递给当前接收用户事件的窗口处

理,window对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的视

图(View),即需要将触摸事件传递给其处理的视图,称之为hit-test view。

         hitText: withEvent:方法的处理流程如下:

        1.首先调用当前视图的pointInside: withEvent:方法(该方法用来判断点击事件发生的

位置是否处于当前视图范围内),若返回NO,则hitTest:withEvent:返回nil。若返回YES,则向

当前视图所有子视图发送hitTest:withEvent:消息。遍历的的顺序是从subviews数组中从末

尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕。

        2.若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束,

如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。   

       解决问题

        这里我们可以知道,在处理视图穿透,或者点击下层视图即可用到hitText: withEvent:

方法。故我们CustomAnnotationView.m中重写hitText: withEvent:方法。并在其中把接收点

坐标系转换成指定坐标系。(这也是网上的统一答案)。

        - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

                    //由上可知,点击点不在当前视图中,故必然返回nil

                    UIView *view = [super hitTest:point withEvent:event];

                            if (view == nil) {

                                        //在这里我们把点击点从CustomAnnotationView坐标系转换成点击按钮的坐标系

                                        CGPoint tempoint = [self.calloutView.navBtn convertPoint:point fromView:self];

                            //判断转换后的点tempoin是否处于点击按钮的rect中,注意,在使用此方法时,两个参数必须属于同一坐标系中

                            if (CGRectContainsPoint(self.calloutView.navBtn.bounds, tempoint))

                                        {

                                                view = self.calloutView.navBtn;

                                        }

                                                       }       

//返回的即为可以接收点击事件的点击按钮

return view;

}

当然,也可以简洁一点:

- (UIView*)hitTest:(CGPoint)pointwithEvent:(UIEvent*)event {

    CGPoint tempoint = [self.calloutView.navigationButton convertPoint:point fromView:self];

    if ([self.calloutView.navigationButton pointInside:tempoint withEvent:event]) {

        return self.calloutView.navigationButton;

    }else{

        return[superhitTest:pointwithEvent:event];

    }

}

      延伸思考

        如果我们要实现一个view覆盖一个button,点击button时处理button的点击事件,点击

其余view范围,处理view自己的事件。同样也要用到hitTest:withEvent:方法。

        解决如下:

        - (UIView*)hitTest:(CGPoint)pointwithEvent:(UIEvent*)event {

                //先把坐标系从self转换到button

                CGPoint touchPoint = [self.btn convertPoint:point  fromView:self];


                //如果点击点在按钮上,返回按钮。如果不在,返回本身相应

                if ([self.btn pointInside:touchPoint withEvent:event]) {

                        return self.btn;

                }else{

                        return [superhitTest:point withEvent:event];    

    }

}

你可能感兴趣的:(关于高德标注点气泡不能点击与hitTest:withEvent:方法详解)