Search code examples
iosobjective-cuiviewuitextfieldhittest

iOS UITextField Outside of SuperView not Responding to Touches


I'm building an iOS 8 app that makes use of the new hidesBarsOnSwipe property on UINavgitationController to hide the nav bar while scrolling. At the same time that the nav bar hides, I'm also programmatically hiding the tab bar. On top of the tab bar, there is a text field which lets users comment on a post (much like Facebook). When the tab bar is hidden (by moving it downward and off the screen), the text field is moved down as well, so that it now sits at the bottom of the screen and so that there's no gap between the bottom of the screen and the text field.

So, things look great. But, turns out that the text field doesn't respond to touch events when it moves to the bottom of the screen. I did some digging and it appears that the reason is because the text field is outside of its superview (the view controller's view), and so touch events will not be sent to the text field.

So I think I've figured out why the issue is occurring, but I haven't yet figured out how to fix it. I've tried messing with hitTest:withEvent: and pointInside:withEvent: but didn't have any luck. Anyone have any solutions?

EDIT: Here is some code to make the question clearer (hopefully). When the nav controller's barHideOnSwipeGestureRecognizer is called, I am running the following code:

- (void)barHideSwipeGestureActivated:(UIPanGestureRecognizer*)gesture
{
    [self animateTabBarUpOrDown:self.navigationController.navigationBar.frame.origin.y >= 0 completion:nil];
}

The method above is the following:

- (void)animateTabBarUpOrDown:(BOOL)up completion:(void (^)(void))completionBlock
{
    if(!self.animatingTabBar && self.tabbarIsUp != up)
    {
        self.animatingTabBar = YES;
        //to animate the tabbar up, reset the comments bottom constraint to 0 and set the tab bar frame to it's original place
        //to animate the tabbar down, move its frame down by its height. set comments bottom constraint to the negative value of that height.
        [UIView animateWithDuration:kTabBarAnimationDuration animations:^{
            UITabBar *tabBar = self.tabBarController.tabBar;
            if(up)
            {
                tabBar.frame = CGRectMake(tabBar.frame.origin.x, tabBar.frame.origin.y - tabBar.frame.size.height, tabBar.frame.size.width, tabBar.frame.size.height);
                self.addCommentViewToBottomConstraint.constant = 0.0f;
            }
            else
            {
                tabBar.frame = CGRectMake(tabBar.frame.origin.x, tabBar.frame.origin.y + tabBar.frame.size.height, tabBar.frame.size.width, tabBar.frame.size.height);
                self.addCommentViewToBottomConstraint.constant = -tabBar.frame.size.height;
            }
        } completion:^(BOOL finished) {
            self.tabbarIsUp = up;
            self.animatingTabBar = NO;
            if(completionBlock)
            {
                completionBlock();
            }
        }];
    }
}

Solution

  • Ok, finally found a solution for this one. I haphazardly messed around with changing the bounds of my view controller's view, but that was too hacky and ultimately didn't accomplish what I wanted it to.

    What I ended up doing was changing my view controller's edgesForExtendedLayout property to be equal to UIRectEdgeAll which basically says that the view should take up the entire screen, and extend above top bars / below bottom bars.

    I had to hack around a little bit with changing auto layout constraints on my text field so that it appeared in the right place at the right time, but overall, the solution was changing edgesForExtendedLayout to be UIRectEdgeAll - this makes the view take up the entire screen, so the text field is now still in the super view even when it animates downward, thus, allowing it to still receive touch events.