You're not traversing the view hierarchy. From the documentation:
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.
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.
Implement like this:
@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
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.
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];