Is it possible for a UIButton (or any other control for that matter) to receive touch events when the UIButton's frame lies outside of it's parent's frame? Cause when I try this, my UIButton doesn't seem to be able to receive any events. How do I work around this?
Yes. You can override the hitTest:withEvent:
method to return a view for a larger set of points than that view contains. See the UIView Class Reference.
Edit: Example:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGFloat radius = 100.0;
CGRect frame = CGRectMake(-radius, -radius,
self.frame.size.width + radius,
self.frame.size.height + radius);
if (CGRectContainsPoint(frame, point)) {
return self;
}
return nil;
}
Edit 2: (After clarification:) In order to ensure that the button is treated as being within the parent's bounds, you need to override pointInside:withEvent:
in the parent to include the button's frame.
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.view.bounds, point) ||
CGRectContainsPoint(button.view.frame, point))
{
return YES;
}
return NO;
}
Note the code just there for overriding pointInside is not quite correct. As Summon explains below, do this:
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if ( CGRectContainsPoint(self.oversizeButton.frame, point) )
return YES;
return [super pointInside:point withEvent:event];
}
Note that you'd very likely do it with self.oversizeButton
as an IBOutlet in this UIView subclass; then you can just drag the "oversize button" in question, to, the special view in question. (Or, if for some reason you were doing this a lot in a project, you'd have a special UIButton subclass, and you could look through your subview list for those classes.) Hope it helps.
@jnic, I am working on iOS SDK 5.0 and in order to get your code working right I had to do this:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if (CGRectContainsPoint(button.frame, point)) {
return YES;
}
return [super pointInside:point withEvent:event]; }
The container view in my case is a UIButton and all the child elements are also UIButtons that can move outside the bounds of the parent UIButton.
Best
In the parent view you can override the hit test method:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint translatedPoint = [_myButton convertPoint:point fromView:self];
if (CGRectContainsPoint(_myButton.bounds, translatedPoint)) {
return [_myButton hitTest:translatedPoint withEvent:event];
}
return [super hitTest:point withEvent:event];
}
In this case, if the point falls within the bounds of your button, you forward the call there; if not, revert to the original implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With