18

I have a UIButton within a view controller which is embedded in a UIPageViewController. Page view controller is in scrolling mode(So No gestures ). When I touch on the button, action method will be called but there is no visible state changes (Highlighted state) is happening for the button. That means button looks like untouched. Observed only in iOS7. Any work around for this?

Case 1 : In Normal ViewController the behaviour of Button with and without Tap

Before tapping After tapping

Case 2 : In one of the PageViewController's viewController the behaviour of Button with and without Tap

Before tapping enter image description here

Yatheesha
  • 10,412
  • 5
  • 42
  • 45
Anil Varghese
  • 42,757
  • 9
  • 93
  • 110
  • Do you use `UIButtonTypeSystem` buttons? Do you configure highlighted state? Is this problem reproducible in new isolated project? – vokilam Mar 05 '14 at 10:37

6 Answers6

16

This usually happens when you put a button in a UIScrollView. UIScrollView has a property called "dalaysContentTouches" which defaults to YES. If it is YES, then the touch down on the button will be delayed (to give time to check if it's a scroll gesture), so you won't see the highlight happen. Still, though, if you tap it, it will register as a button press, without ever becoming highlighted.

I'm not positive what your setup is exactly, but it seems like a similar issue. Check any gestureRecognizers involved in your UI and check the values for "delaysTouchesBegan" and "delaysTouchesEnded".

**edited after experimentation**

I just tried this out on iOS 7.0 and it seemed to do the trick.

-(void)viewDidAppear:(BOOL)animated {
    NSArray *subviews = self.pageViewController.view.subviews;
    NSArray *viewHierarchy = [@[self.pageViewController.view] arrayByAddingObjectsFromArray:subviews];
    int i = 0;
    for (UIView *viewToCheck in viewHierarchy) {
        for (UIGestureRecognizer *gestureRecognizer in viewToCheck.gestureRecognizers) {
            NSLog(@"%d gestureRecognizer: %@", i++, gestureRecognizer);
            gestureRecognizer.delaysTouchesBegan = NO;
        }
    }
}

I get this output

0 gestureRecognizer: <UIScrollViewDelayedTouchesBeganGestureRecognizer: 0x8e9b510; state = Possible; delaysTouchesBegan = YES; view = <_UIQueuingScrollView 0x9b7f800>; target= <(action=delayed:, target=<_UIQueuingScrollView 0x9b7f800>)>>
1 gestureRecognizer: <UIScrollViewPanGestureRecognizer: 0x8e9ba10; state = Possible; delaysTouchesEnded = NO; view = <_UIQueuingScrollView 0x9b7f800>; target= <(action=handlePan:, target=<_UIQueuingScrollView 0x9b7f800>)>; must-fail = {
        <UIScrollViewPagingSwipeGestureRecognizer: 0x8e9bec0; state = Possible; view = <_UIQueuingScrollView 0x9b7f800>; target= <(action=_handleSwipe:, target=<_UIQueuingScrollView 0x9b7f800>)>>
    }>
2 gestureRecognizer: <UIScrollViewPagingSwipeGestureRecognizer: 0x8e9bec0; state = Possible; view = <_UIQueuingScrollView 0x9b7f800>; target= <(action=_handleSwipe:, target=<_UIQueuingScrollView 0x9b7f800>)>; must-fail-for = {
        <UIScrollViewPanGestureRecognizer: 0x8e9ba10; state = Possible; delaysTouchesEnded = NO; view = <_UIQueuingScrollView 0x9b7f800>; target= <(action=handlePan:, target=<_UIQueuingScrollView 0x9b7f800>)>>
    }>

which reveals a UIScrollViewDelayedTouchesBeganGestureRecognizer, which seems to be a custom recognizer for the PageController designed to do exactly that to your button...

But! Set its delaysTouchesBegan property to NO, and the button highlight appears immediately on press. Hope that works for you too.

devdavid
  • 1,571
  • 10
  • 14
1
  • check your UIButton states defined in xib or storyboard (but since you said it's only in iOS7, shouldn't be a problem)

  • check, which State your Button has after click in your IBAction method

  • try to set your recommend Button state in the IBAction method

    yourButton.higlighted = YES;
    
    //or yourButton.selected = YES; setting selected state 
    
vokilam
  • 10,153
  • 3
  • 45
  • 56
longi
  • 11,104
  • 10
  • 55
  • 89
1

The same issue, I was facing with the UITableViewController. I'm not sure about that it works with UIPageViewController, but hopefully it helps.

self.PageView.delaysContentTouches = NO;

In ViewController:

for (id obj in self.View.subviews)
    {
        if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"])
        {
            UIScrollView *scroll = (UIScrollView *) obj;
            scroll.delaysContentTouches = NO;
            break;
        }
    }
Kumar KL
  • 15,315
  • 9
  • 38
  • 60
1

Try to set the Button state to highlighted using the code in you IBAction method associated with the button.

Button.higlighted = YES;

or you can use the selected state when the button is clicked in your action method

[button setSelected:YES];
Kumar KL
  • 15,315
  • 9
  • 38
  • 60
Rohit
  • 1,189
  • 12
  • 23
0
UIColor *textColorHighlighted=[UIColor blackColor] ;

[_button setTitleColor:textColorHighlighted forState:UIControlStateHighlighted];
daniel kilinskas
  • 3,538
  • 3
  • 16
  • 10
0

I don't know if people still come across this post, but I did, and I spent so many hours trying to find a solution, and I finally did, so for people who have the same problem and are working in Swift, this worked for me:

Swift 3.1:

override func viewDidLoad() {
    super.viewDidLoad()
    let views = view.subviews

    for view in views {

        if let scrollView = view as? UIScrollView {
            scrollView.delaysContentTouches = false
        }
    }
}
JoniVR
  • 1,839
  • 1
  • 22
  • 36