Reputation: 83
I have a three view controllers and a view.
one contains the main view, the other contains the customized navigation bar, and the third contains the view(aka subview of the third view controller).
when the app is loaded, navigationbar view will be visible along with the subview. Inside the subview I have a button that i want to place on top of the navigationbar view. Unfortunately i cannot do this straightforward using something like navigationitem.setrightbutton...or any other such methods (everything is coded, no nibs).
So what i am doing is setting my button frames y value to a negative value. This means that the button is out of the frame bounds of the subview, but it achieves what i want which is placing the button on top of the navigationbar.
Unfortunately no click events are passed to the button as it is outside the subview frame bounds...
I have tried overriding pointinside and hittest of the view but nothing is working.
I hope I have made myself clear. Any code that would solve this issue would be much appreciated.
Upvotes: 4
Views: 3722
Reputation: 3867
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if yourButton.frame.contains(point) {
let convertedPoint = yourButton.convert(point, from: self)
return yourButton.point(inside: convertedPoint, with: event)
}
return super.point(inside: point, with: event)
}
Upvotes: 0
Reputation: 40995
Touch events are only propagated within the bounds of a view. Although it's possible to place a subview outside its parents bounds and still see it, events won't be passed to it.
The underlying mechanism for handling events is the following method of UIView:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
This method is responsible for deciding which view a given touch event should go to. When you touch the screen, the hitTest method of the root view (the window) is called, and it will call the method on it's subviews, and they will call the method on their subviews, and so on.
In principle you could create a custom window class and override the hitTest method in your window to force it to forward events to the button even though it's outside of its parent's bounds, but this is quite fiddly to do correctly. It would be something like this:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGRect rect = WORK_OUT_WHERE_THE_BUTTON_RECT_IS_RELATIVE_TO_THE_WINDOW;
if (CGRectContainsPoint(rect, point))
{
return theButtonView;
}
else
{
return [super hitTest:point withEvent:event];
}
}
Instead, I suggest you save yourself a lot of hassle and change the way your app works by adding your button as a subview of the navigation bar instead of using negative positioning to place it there.
Upvotes: 2