hitTest:WithEvent和Subviews [英] hitTest:WithEvent and Subviews

查看:93
本文介绍了hitTest:WithEvent和Subviews的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个视图,但我想让1个视图(虚拟)更大。
如果我将tapGesture放在v1上,则点击手势可以使用更大的命中区域
但是如果我将tapGesture放在v2上它不起作用(实际上它根本不识别tapGesture,即使不在原始范围内)即使我循环通过我的TestView1 hittest方法并且点包含在框架中。

I have 2 views , but i want to make 1 view (virtually) bigger. if I place my tapGesture on v1, the tap gesture works with a bigger hit area but if I place my tapGesture on v2 it doesn't work ( actually it doesn't recognizes the tapGesture at all, even not inside the original bounds ) even though i loop through my TestView1 hittest method and the points get contained in the frame.

#import "ViewController.h"

@interface TestView1 : UIView
@end

@implementation TestView1

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    CGFloat radius = 100.0;
    CGRect frame = CGRectMake(0, 0,
                              self.frame.size.width + radius,
                              self.frame.size.height + radius);

    if (CGRectContainsPoint(frame, point)) {
        return self;
    }
    return nil;
}

@end

@interface TestView2 : UIView
@end

@implementation TestView2

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    CGFloat radius = 100.0;
    CGRect frame = CGRectMake(0, 0,
                              self.frame.size.width + radius,
                              self.frame.size.height + radius);

    if (CGRectContainsPoint(frame, point)) {
        return self;
    }
    return nil;
}
@end

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    TestView1 *v1 = [[TestView1 alloc] initWithFrame:CGRectMake(50.f, 50.f, 100.f, 100.f)];
    [self.view addSubview:v1];

    TestView2 *v2 = [[TestView2 alloc] initWithFrame:CGRectMake(0.f, 0.f, 100.f, 100.f)];
    v2.backgroundColor = UIColor.yellowColor;
    [v1 addSubview:v2];

    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
    [v2 addGestureRecognizer:gesture];
}

- (void) panGesture:(UIPanGestureRecognizer *)recognizer
{
    NSLog(@"tap");
}
@end


推荐答案

您没有遍历视图层次结构。从文档中:

You're not traversing the view hierarchy. From the documentation:


此方法通过向每个子视图发送pointInside:withEvent:消息来遍历视图层次结构,以确定应从哪个子视图接收触摸事件。如果pointInside:withEvent:返回YES,则遍历子视图的层次结构;否则,将忽略其视图层次结构的分支。

This method traverses the view hierarchy by sending the pointInside:withEvent: message to each subview to determine which subview should receive a touch event. If pointInside:withEvent: returns YES, then the subview’s hierarchy is traversed; otherwise, its branch of the view hierarchy is ignored.

您只需要实现 pointInside:withEvent:。你不应该覆盖 hitTest:withEvent:,因为标准实现将调用你的 pointInside:withEvent:的实现并且做为你所有遍历层次结构的艰苦工作。

You only need to implement pointInside:withEvent:. You shouldn't override hitTest:withEvent: because the standard implementation will call your implementation of pointInside:withEvent: and do for you all the hard work of traversing the hierarchy.

这样实现:

@interface TestView1 : UIView
@end

@implementation TestView1

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGFloat radius = 100.0;
    CGRect frame = CGRectMake(0, 0,
                              self.frame.size.width + radius,
                              self.frame.size.height + radius);

    return (CGRectContainsPoint(frame, point));
}

@end

@interface TestView2 : UIView
@end

@implementation TestView2

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGFloat radius = 100.0;
    CGRect frame = CGRectMake(0, 0,
                              self.frame.size.width + radius,
                              self.frame.size.height + radius);

    return (CGRectContainsPoint(frame, point));
}

@end

现在,您是否需要两者意见取决于你。您已经成功扩展了v1的可触摸区域,使用上面的代码,您可以使用v2作为v1的子视图。

Now, whether you need both the views is up to you. You had already succeeded in expanding touchable area of v1, and with the code above you can do it with v2 as a subview of v1.

然而, TestView1 TestView2 实现完全相同(即使在您的原始帖子中),那么为什么需要将它们分开?您可以使v1和v2成为同一类的两个实例,例如 TestView ,并按如下方式对它们进行实例化:

However, TestView1 and TestView2 implementations are exactly the same (even in your original post), so why do you need to have them separate? You could make v1 and v2 both instances of the same class, e.g. TestView, and instantiate them as follows:

TestView *v1 = [[TestView alloc] initWithFrame:CGRectMake(50.f, 50.f, 100.f, 100.f)];
[self.view addSubview:v1];
v1.clipsToBounds = YES;

TestView *v2 = [[TestView alloc] initWithFrame:CGRectMake(0.f, 0.f, 100.f, 100.f)];
v2.backgroundColor = UIColor.yellowColor;
[v1 addSubview:v2];

这篇关于hitTest:WithEvent和Subviews的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆