美文网首页
关于高德标注点气泡不能点击与hitTest:withEvent:

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

作者: MY无名 | 来源:发表于2020-03-23 15:37 被阅读0次

           前言

            最近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:

          本文链接:https://www.haomeiwen.com/subject/sgkwyhtx.html