How to detect the touch point of iCarouselButtonDemo? - ios

I am using iCarouselButtonDemo to create an arc button menu. I want to disable the scrolling when user touch the space other than the buttons. But now we can scroll the view by touching every point of the UIView. How can I detect the touch point of the view and disable the scrolling when user touch the outside of the 5 buttons
This is my view. This is scrolling when I touch even the bottom of the view. How can I stop it?
Thanks

In the iCarousel implementation file, you will add the following code in gestureRecognizerShouldBegin method. So it looks like this. It firstly get the touch point in the iCarousel view, and find the inner most view responding to the touch through hitTest. If the view is not a button, you stop the pan gesture.
if ([gesture isKindOfClass:[UIPanGestureRecognizer class]])
{
CGPoint point = [gesture locationInView:self];
UIView *touchedView = [self hitTest:point withEvent:nil];
if (![touchedView isKindOfClass:[UIButton class]]) {
return NO;
}
//ignore vertical swipes

Related

Detecting Touches outside UIView subview

I'm modulating an app I'm making. I want my subview to detect touches at any location on screen either to the left or right. Now that it is a subview, I'm only able to detect touches within its bounds. I tried changing the bounds of my subview, but that causes the subview to disappear from the screen completely. Can my touch location be detected outside my subview?
UITouch *touch = [touches anyObject];
touchLocation = [touch locationInView:self.superview];
if(touchLocation.x < self.center.x) //touches occur to the left
{
right = false;
}
if(touchLocation.x > self.center.x) //touches occur to the right
{
right = true;
}
If your subview is the view which implement the code to intercept the touch, you can intercept touches just on that view.
If you want intercept touch out of the subview, you must (and is conceptually right) add the intercept code in your superview.
A gesture recognizer could work for your situation, depending on what your trying to pick up on. If your situation fits you can add one to the subviews window. You can access it via your views window property. Then inside of your gesture recognizer code you can use the "Hit testing in a view" and "Converting between view coordinates" methods of UIView to find out if the touch was in your view. Be sure to remove the gesture recognizer from the window when your object is removed from the superview or it's dealloced.

How to allow sibling UIViews to handle different gestures?

I have a UIView which has two subviews, one is a UIScrollView and the other is a container view for a few other subviews. The container view is covering the scroll view completely.
Views that need to handle gestures:
UIScrollView - should handle the default pinch and pan gestures
Container view - none
Container view subviews - should handle tap gesture
Now in order for the tap gestures to be handled by the container view subviews I implemented pointInside:withEvent: for the container view. If it recognises the point is inside one of its subviews it returns YES. This works fine. The problem is that when I pinch or pan and my finger initially touches one of the container view subviews it doesn't work. When I pinch or pan on an empty area of the container view it works as it should.
Any suggestions how to make it work?
EDIT:
I've implemented hitTest:withEvent: for the main view and got the same behavior.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitTestView;
for (UIView *subview in [self.subviews reverseObjectEnumerator])
{
hitTestView = [subview hitTest:[self convertPoint:point
toView:subview]
withEvent:event];
if (hitTestView && ![hitTestView isKindOfClass:[ContainerView class]])
{
break;
}
}
return hitTestView;
}
On the bottom line the question here is how does one view only handles some gestures and passes on other gestures so an underlying view could handle them.
I've read quite a lot about the subject and tried different approaches but couldn't find a straightforward solution to what seems like a pretty common issue.
You don't actually need to handle pinch and pan gesturese on UIScrollView manually, it's going to happen automatically.
For handling container view subviews you can use UITapGestureRecognizer. For each view you need to handle tap use:
UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFirstSubview:)];
[firstSubview addGestureRecognizer:tapRecognizer];
Handler method:
- (void)handleTapFirstSubview:(UITapGestureRecognizer *)tapRecogmizer
{
// handle tap here
}

UIView handle and pass touch events to next sibling view

I'm building an iOS app that has a custom UIView upon a UIScrollView which in turn has a subview.
Here's the layout structure:
Note that the custom UIView(called "Detected Object Hint View") is not a subview of ScrollView, it's a sibling view of UIScrollView. And I want to respond to tap gesture on the custom UIView, so I've added UITapGestureRecognizer to the UIView, and it works for tap, but the UIScrollView will never get any touch events (not responding to scroll or zoom gesture).
I've googled a while, and a lot of people pointed out that in order for other view to respond to the touch events, I should implement the following method:
- (id)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *hitView = [super hitTest:point withEvent:event];
if (hitView == self){
return nil;
}
else {
return hitView;
}
}
But once I've added this method to my custom UIView, it will not respond to tap gesture either (of course).
So I'm wondering how can I handle the tap gesture on my custom UIView and pass the touch events to UIScrollView as well?
Big thanks!

Page-based application and gesture recognizer

I have created a page-based application in Xcode 4, for iPad iOS5.
When I run the app, I can see the pages in the book and can flip them back and forward,
by tap on the screen or by moving the finger from left to right, or right to left.
My problem is that no matter where I'm pressing in the screen, in the borders, the page turns.
I had managed to cancel the flip with fingers with this code:
for (UIGestureRecognizer *gR in self.pageViewController.gestureRecognizers)
{
if ([gR isKindOfClass:[UIPanGestureRecognizer class]])
{
[[gR view] removeGestureRecognizer:gR];
}
}
How can I define a specific area in the screen that when I tap on it, and only it, the page will turn?
I ask this because I put toolbar in the bottom of the screen and when I click on a button in the toolbar the page flips. I want to put 2 arrows on the screen that only when I press on them the page will flip.
Sorry if my explanation is a little bit rusty. Thank you all.
Cipramill's answer is correct -- here are more details.
The IOS documentation suggests adding new Views to delineate the areas where you wish the page turning gestures to be active, but this method is much simpler. Adding code to the default template set up by Xcode 4 in MQ1RootViewController.h and MQ1RootViewController.m:
Change interface line in MQ1RootViewController.h:
#interface MQ1RootViewController : UIViewController <UIPageViewControllerDelegate,
UIGestureRecognizerDelegate>
Add this code to the very bottom of viewDidLoad in MQ1RootViewController.m:
for (UIGestureRecognizer *gR in self.pageViewController.gestureRecognizers) {
gR.delegate = self;
}
Add this method to MQ1RootViewController.m:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]
|| [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
CGPoint point = [touch locationInView:self.view];
if(point.x < 100 || point.x > 924) return YES;
}
return NO;
}
Note that the "swipe" gesture is actually derived from a "pan" gesture by the page view controller object.
The above limits the gestures to the left and right edges of the screen. This allows gestures to be used to interact with objects in the center of the screen without accidentally changing the page with an errant swipe.
you could hook into the the gesture system and define which area to accept touches for.
In this explanation I assume your RootViewController has a UIPageViewController as a child VC:
-Set your root view controller to implement UIGestureRecognizerDelegate
-Take over all gesture recognizers for your pageVC in your RootViewControllers ViewDidLoad:
for (UIGestureRecognizer *gR in self.pageVC.gestureRecognizers) {
gR.delegate = self;
}
-Finally implement the gesture recognizer in your RootViewController and define which zones you want to ignore:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
CGPoint point = [touch locationInView:self.view];
//Examine point and return NO, if gesture should be ignored.
}
return YES;
}
Hope this helps

Detecting swipe gestures on UITableViewCell inside UIScrollView

I am hoping someone will be able to help me with a problem that is doing my head in at the moment!
Given the following view hierarchy
I want to be able to detect swipe gestures on my custom UITableViewCell.
I have subclassed the UIScrollView and have a hitTest:withEvent: method that checks whether I am touching the tableview cell (or its content) or not, in which case I set the following scroll view properties:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if ([result.superview isKindOfClass:[UITableViewCell class]] || [result.superview tag] == SUBVIEW_TAG)
{
self.canCancelContentTouches = NO;
self.delaysContentTouches = YES;
} else {
self.canCancelContentTouches = YES;
self.delaysContentTouches = NO;
}
return result;
}
I have also implemented:
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
if (view.tag == SUBVIEW_TAG || [[view superview] isKindOfClass:[UITableViewCell class]])
return NO;
return YES;
}
And am returning NO in case the view being touched is the table view cell.
These methods are all getting called and performing their actions as expected, but I am still unable to stop the UIScrollView from "hogging" the swipe gesture.
The interesting thing is that if I include the UIView that contains the tableview and cell on both of the methods above (the one with SUBVIEW_TAG) it works perfectly so I am guessing it must be something to do with the fact that UITableView inherits from UIScrollView.
My main goal is to be able to swipe on the cell to reveal more options for the cell. A horizontal swipe anywhere else on that view would be captured by the scroll view and shift the content horizontally as per its normal behaviour.
Any ideas would be very much appreciated!
Thanks!
Rog
I had a similar problem with a swipe detect for a component inside a scrollview and I was able to resolve it with
[scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeGesture]
Where scrollView is the scroll view object that acts like container and swipeGesture is the component swipe gesture object inside scrollview.
So, you can define a swipe for the cell object like this (for right swipe in the example, custom it as you want)
UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(yourMethod)];
[rightSwipeRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[cell addGestureRecognizer:rightSwipeRecognizer];
and then do
[scrollView.panGestureRecognizer requireGestureRecognizerToFail:rightSwipeRecognizer]
The documentation of requireGestureRecognizerToFail says:
This method creates a relationship with another gesture recognizer
that delays the receiver’s transition out of
UIGestureRecognizerStatePossible. The state that the receiver
transitions to depends on what happens with otherGestureRecognizer:
If otherGestureRecognizer transitions to
UIGestureRecognizerStateFailed, the receiver transitions to its normal
next state.
if otherGestureRecognizer transitions to
UIGestureRecognizerStateRecognized or UIGestureRecognizerStateBegan,
the receiver transitions to UIGestureRecognizerStateFailed.
An example where this method might be called is when you want a
single-tap gesture require that a double-tap gesture fail.
Availability Available in iOS 3.2 and later.
Hope helps!
The solution is pretty simple. All you need to do is add UIScrollView inside you UITableViewCell. It will prevent "hogging" effect during swipe gesture.

Resources