iOS temporarily disable Page View Controller swiping - ios

I have a setup where I have a Page View Controller set up to navigate between different views.
In some of these views I will have a custom drawing view where the user can draw with their finger to create a picture.
The problem with this, the user is not able to make a drawing gesture left/right because the page view controller will take over and navigate to a different view.
I was wondering what a good approach would be to temporarily disable the swiping for the page view controller to allow the user to draw.
I was thinking when the user first interacts with the drawing view it would disable the page swiping and create a finished drawing button. When this button is clicked it would reenable the page swiping. Does this seem reasonable, or does anybody know of any better approaches?

Using this you can stop Scrolling
for (UIScrollView *view in self.pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
view.scrollEnabled = NO;
}
}

I'd look into this UIGestureRecognizerDelegate method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
Here you can "kill" the page view controller's gesture recognizer by disabling and re-enabling it:
if (/* otherGestureRecognizer is page view controller's */) {
otherGestureRecognizer.enabled = NO;
otherGestureRecognizer.enabled = YES;
}

Related

UIPageViewController crashes when holding down a button while it's animating

I have UIPageViewController that animates programatically. The problem is that the view controllers inside it has UIButtons inside them. When I hold down a button and wait until the UIPageViewController animates, the app crashes with the error:
'Failed to determine navigation direction for scroll'
What I think I need to do is to somehow fake that the user releases the button before the UIPageviewController animates.
However, [self.button sendActionsForControlEvents:UIControlEventTouchCancel]; doesn't seem to do the trick. Neither do UIControlEventTouchUpInside.
Is there a better way do to it or am I using sendActionsForControlEvents wrong?
All sendActionsForControlEvents: does is call any methods you've assigned to the control events passed in for the button. It doesn't call any internal methods to programmatically lift up touches or anything like that.
Right before you programmatically animate your page view controller, try using this method to effectively cancel any touches on the pan gesture recognizer of the page view controller's internal scroll view:
- (void)cancelPanGestureTouchesOfPageViewController:(UIPageViewController *)pageVC
{
// Since UIPageViewController doesn't provide any API to access its scroll view,
// we have to find it ourselves by manually looping through its view's subviews.
for (UIScrollView *scrollView in pageVC.view.subviews) {
if ([scrollView isKindOfClass:[UIScrollView class]]) {
// We've found the scroll view, so use this little trick to
// effectively cancel any touches on its pan gesture recognizer
BOOL enabled = scrollView.panGestureRecognizer.enabled;
scrollView.panGestureRecognizer.enabled = !enabled;
scrollView.panGestureRecognizer.enabled = enabled;
}
}
}
(Note that this is messing with the internal view hierarchy of UIPageViewController, so this method is kind of ugly and may break in the future. I generally don't recommend doing stuff like this, but I think in this instance it should be okay.)

iOS gesture collisions between slider and pan gesture on controller

I am using ECSlidingViewController for hamburger menu and I added code to my viewDidLoad method:
[self.slidingViewController.topViewController.view addGestureRecognizer:self.slidingViewController.panGesture];
Now I have pan gesture to show right menu or to hide. It's okay. But I have on view slider and it's really hard to get him working. I must tap on exact position. Is it possible to set that in exact rectangle (in view that contains slider) the slider would be answering on gesture and on other parts it would be working as now?
And one more question. When I have navigation controller with table and then I went on detail and then I show right menu it's okay but when I want to close it by pan I first go back in navigation and then close menu. Is it possible to change this order?
Have you tried setting UIGestureRecognizerDelegate and handling the both gesture recognizes in similar fashion as described in FAO?
e.g.:
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([otherGestureRecognizer.view isKindOfClass:[UISlider class]]) {
return YES;
} else {
return NO;
}
}

Cancel gesture recognizer on button action

I'm working on an iPad app. I have a view in which the user can draw with his finger. This view has a subview, which is a calculator, and which have buttons.
I would like that when the user touch a button, the superview (in which the user can draw) doesn't take into account this touch. (so the user doesn't draw when he touches the calculator)
Preferably, I would like to not change the code of the calculator view and the code of my superview. I have only access to them via properties of another class.
Is there a way to solve the problem please? I have tried exclusiveTouch, but it doesn't work.
If you have access to the button action and the drawing gesture you can simply set:
gesture.enabled = NO;
To cancel the current gesture processing and / or prevent it from starting. When you want to reenable the gesture depends on what type it is and how it's used but doing it immediately (on the next line) will probably work ok.
Try this but include UIGestureRecognizerDelegate in your header file.
This is from apple "SimpleGestureRecognizers" example-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
// Disallow recognition of tap gestures in the segmented control.
if ((touch.view == YourButton))
{
//change it to your condition
return NO;
}
return YES;
}

Tap on UIBarButtonItem is not ignored by TapGestureRecognizer

I have a view with a UIToolbar with a few UIBarButtonItems and a UITableView containing some UITextFields.
I would like to dismiss the keyboard for a textfield with a tap anywhere. Therefore I added a TapGestureRecognizer to the view. To avoid that the TapgestureRecognizer handles taps on the UIBarButtonItems I added the following method (delegate is set).
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
UIView *view = touch.view;
while (view) {
NSLog(#"Class of view: %#", NSStringFromClass([view class]));
view = view.superview;
}
// Disallow recognition of tap gestures in the toolbar
if ([touch.view isKindOfClass:[UIToolbar class]]) {
return NO;
}
if ([touch.view.superview isMemberOfClass:[UIToolbar class]]) {
return NO;
}
return YES;
}
A UIBarButtonItem is not a view itself, but it has UIToolbar as its superview. When I use the above method, the check for isKindOfClass:[UIToolbar class] does not seem to work for all taps on the toolbar. However the check for the superview with isMemberOfClass:[UIToolbar class] works.
I don't understand this. Maybe someone can explain this behavior?
You shouldn't rely on the view hierarchy around private view classes. It could change at any time.
A better approach is to add the gesture to the table view (or other appropriate view which represents the area you're interested in). Just be sure to enable and disable the gesture at appropriate times so as not to block the usual table operation.

iPad - PageViewController - Show next view controller on button click

I'm using UIPageViewController in my application that shows all the images similar to a book. Its working fine.
What I want to do now:
I want to place a button on top left corner and on click it will show a pop over view controller which has a table view with 7 cells. Each cell will show different URL. On click of the table cell, it will push a view controller with web view.
What's the problem
The problem is that I placed the button on top left and created a segue to show popover. But on click of button it goes to previous page and on next clicks it will finally reach page 1. then in page 1, it will show the pop over. I didn't understand why is it happening like this.
And even after showing popover, its not showing next view with website.
How to do it?
The trick is that UIPageViewController's gesture recognizers take over that area. In particular, the tap handler; so your button only gets hit when the tap recognizer does not take it as meaning to go to the previous page.
Quickest solution is to set yourself to the delegate of its recognizers
for (UIGestureRecognizer *recognizer in pageViewController.gestureRecognizers)
recognizer.delegate = self;
and then implement the delegate telling them to let controls get touches
- (BOOL)gestureRecognizer:(UIGestureRecognizer *) __unused gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIControl class]])
return NO;
return YES;
}
which ought to sort you nicely.

Resources