Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Touch events within ~8 pixels of nav bar not called

I have an application with three buttons (actually UIView's) laid out horizontally underneath the navigation bar.

The three buttons are of substantial enough size (larger than the back button, for example), however they won't respond to touches when the hit is in the top third part, roughly.

I'm aware that this area directly underneath the nav bar is sort of 'reserved' for the back button and other UINavigation items having a touch area that expands beyond the navigation bar (by quite a significant margin), however in some instance there isn't even a navigation item nearby to steal the event, and my views still don't respond.

The weird thing is that I am getting a call to the hitTest method in my UIView, just never a touchesBegan/Ended/etc.

The result is that it is very difficult to press the buttons and if one is anywhere near a UINavigationItem, the item will steal the event, even though in hitTest I am returning the correct UIView to the system.

Unfortunately I am the implementer and not the designer so a design change is a last resort.

Any ideas? Thanks!

like image 937
Sam Avatar asked Feb 02 '23 12:02

Sam


2 Answers

You have to subclass your UINavigationBar and in your CustomNavigationBar do this:

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    if ([self pointInside:point withEvent:event]) {
        self.userInteractionEnabled = YES;
    } else {
        self.userInteractionEnabled = NO;
    }

    return [super hitTest:point withEvent:event];
}

Info about how to subclass UINavigationBar you can find here.

like image 97
Andrei Radulescu Avatar answered Feb 11 '23 01:02

Andrei Radulescu


The code provided by @Andrei will cause controller stack inconsistency on iOS 7 when quickly push and pop controllers. The system itself will change the userInteractionEnabled property before and after push/pop animations. Here is how I fixed this issue.

@interface DMNavigationBar ()

@property (nonatomic, assign) BOOL changingUserInteraction;
@property (nonatomic, assign) BOOL userInteractionChangedBySystem;

@end

@implementation DMNavigationBar

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (self.userInteractionChangedBySystem && self.userInteractionEnabled == NO)
    {
        return [super hitTest:point withEvent:event];
    }

    if ([self pointInside:point withEvent:event])
    {
        self.changingUserInteraction = YES;
        self.userInteractionEnabled = YES;
        self.changingUserInteraction = NO;
    }
    else
    {
        self.changingUserInteraction = YES;
        self.userInteractionEnabled = NO;
        self.changingUserInteraction = NO;
    }

    return [super hitTest:point withEvent:event];
}

- (void)setUserInteractionEnabled:(BOOL)userInteractionEnabled
{
    if (!self.changingUserInteraction)
    {
        self.userInteractionChangedBySystem = YES;
    }
    else
    {
        self.userInteractionChangedBySystem = NO;
    }

    [super setUserInteractionEnabled:userInteractionEnabled];
}

@end
like image 21
nonamelive Avatar answered Feb 11 '23 02:02

nonamelive