Disabling only left swipe on UITableViewCell. - ios

My main view controller includes a table view and also a separate view on the right that folds in when the user pans left.
I have setup a PanGestureRecogniser on this controller so that the user can use it to switch between the two views. It works fine except for one issue.
When there are only one or two cells, the user needs to pan using the empty area at the bottom not covered by cells. When there are cells that cover the entire view, or when the user pans left, the cell's swipe to delete function gets activated, since a pan gesture always fires a swipe gesture.
I want to keep the swipe-to-delete feature, but ONLY when a user swipes right on a cell.
Any left swipes/pans should always unfold the second view on the right. I'm using a custom UITableViewCell subclass. Is there any way to disable ONLY the left swipe to enter the delete mode?

This is entirely possible.
Here's the code. Add the same to your - (void) viewDidLoad method:
UISwipeGestureRecognizer * newSwipeGR = [[UISwipeGestureRecognizer alloc] initWithTarget:nil action:nil];
newSwipeGR.direction = UISwipeGestureRecognizerDirectionLeft;
newSwipeGR.numberOfTouchesRequired = 1;
[self.myTableView addGestureRecognizer:newSwipeGR];
Still enable the deletion mode as normal, but you're now find that the delete swipe only works in one direction.

Related

swipe left to pull next view according to thumb speed

I am working on and app in which i have to take user to next view if user swipe next. Simply swipe gesture working dine.
But the problem is a little of left swipe take the user to next view.
What i want to implement is to make user see pulling next view by itself and next view coming over to the present view according to the thumb swipe speed. Something like shown in the screenshot
See that library
https://github.com/zhxnlai/ZLSwipeableView
The same thing happening , if a required velocity is not there than card is not discarded , go to ZLSwipeableView and you can find code there , the hint you needed , like that
CGPoint velocity = [recognizer velocityInView:self];
CGFloat velocityMagnitude = sqrt(pow(velocity.x,2)+pow(velocity.y,2));
CGPoint normalizedVelocity = CGPointMake(velocity.x/velocityMagnitude, velocity.y/velocityMagnitude);
Use UIpanGestureRecognizer, track the area swiped and move to next Screen or you have to use UIContainer

Forwarding a gesture to superview

So I have got this scenario:
-NavigationController
-PageViewController
-MapViewController
-UIView
-MKMapView (Full Screen)
-OtherViewController
So basically, I want it to switch pages (viewcontrollers) when catching the UIScreenEdgeGesture. But having the map in one of them, this doesn't work properly.
I have researched a lot (!) about this but still haven't found the right solution.
I believe that the correct approach here is to delegate this gesture to the nextResponder in the hierarchy.
So I have successfully captured the gesture when the user swipes on the left edge of the screen.
Right now my issue is I can't manage to pass the gesture to the UIView (MKMapView.superview).
I have two questions :
// 1. How to do it
// 2. Is this the right approach?
Let me know your thoughts on this one please!
EDIT 1:
Adding some code and Images of story board
UIScreenEdgePanGestureRecognizer *popRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:[self.view superview] action:#selector(handlePopRecognizer:)];
popRecognizer.edges = UIRectEdgeLeft;
popRecognizer.delegate = self;
[self.mapView addGestureRecognizer:popRecognizer];
EDIT 2: I want this behaviour : Use UIScreenEdgePanGestureRecognizer without moving MKMapView
But when the gesture is recognized, I want it to switch to the page on the left (OtherViewController)
FINAL EDIT: THE workaround that I've come up with consists in putting a clear view on top of the map, leading to the desired behaviour. Not happy with the solution, but it works for now.
When you create your gesture, make the target the superview, and call the method in the superview for the action, something like:
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:[self.view superview] action:#selector(swipeHandler:)];
Don't know if MKMapView.superview would work, that depends on if MKMapView is an instance. Hard to know what you're referring to without code.

Unable to override swipe to delete cell functionality for iOS v > 6.1

We are developing an iPad application where entire UI is created using Storyboard file.
In one of the view controller scene, there is a UITableView which contains a custom cell.
When I swipe to the table cell, a delete button appears for that.
How to disable this swipe to delete functionality. We have our own Edit button on top navigation bar, which sets UITableView's editingMode. We require to disable swipe to delete funcitonality.
Here is what we have already tried:
1. Overriden swipe gesture method:
UISwipeGestureRecognizer *gestureR = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSwipeFrom:)];
[gestureR setDirection:UISwipeGestureRecognizerDirectionRight];//|UISwipeGestureRecognizerDirectionRight)];
[myTableView addGestureRecognizer:gestureR];
We have tried this gesture with both, myTableView as well in CustomCell file.
2. Remove swipe gesture method:
UIGestureRecognizer* swipe = [[self.tableView gestureRecognizers] objectAtIndex:2];
[myTableView removeGestureRecognizer:swipe];
Both of those code blocks are not working for us.
This issue is there only for the iOS 7 only, as there is default swipe to delete given for UITableView.
Please suggest a solution for this.
(1.) is not really an override. It seems adding multiple recognisers could have undefined results.
(2.) looks like a private API hack, so also not advisable.
Instead, the editing behaviour of a table view is controlled by overriding these methods:
- tableView:willBeginEditingRowAtIndexPath:
– tableView:editingStyleForRowAtIndexPath:
See the documentation for details.

iOS: Swipe up gesture recognizer not working

My table view has a text field above it. And whenever the text field is focussed, a swipe gesture is registered. When the swipe gesture is recognized, the keyboard is dismissed. The code is working for all gestures except for swipe up gesture is not working. This is my code
swipe = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(dismissKeyboard)];
[swipe setDirection:UISwipeGestureRecognizerDirectionUp];
Can someone please let me know if there is any problem?
if all the other gestures works, that means there is no logic problem.
check out spelling errors.
and reapply the swipe gesture, and check out everything (outlets etc.).
I don't know about this case, but I know that when I've had gestures on a custom container view and then added a child view with its own gestures, I've had to iterate through the child's gestures and tell them to require my gestures to fail (i.e. mine take precedence). I've done this with scroll views successfully:
for (UIGestureRecognizer *gesture in self.scrollView.gestureRecognizers)
{
[gesture requireGestureRecognizerToFail:myGesture];
}
The only times I've had problems with that are views like UITextView which remove and add gestures as you go in and out of edit mode, so that's a hassle.
Also, while I tried this with standard gestures, I've subsequently shifted to custom gestures that I've programmed to failed as quickly as possible (check the start location and fail immediately if it won't support the direction my gesture requires, rather than waiting for a bunch of touchesMoved to come to the same conclusion). If you don't want to interfere with the child view's gestures, be as aggressive as possible in letting yours fail. Maybe this isn't an issue with a swipe gesture, but it's a possible consideration if you find that your gestures end up changing the behavior of the child view noticeably.
But I suspect you'll probably just have to figure out which views have the gestures that are interfering with yours and make them require yours to fail first.
Any chance you're colliding with one of the scrollview's gestures? It doesn't seem likely if your other gestures are working, but it might be worth at least trying the gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: method in the UIGestureRecognizerDelegate protocol.

UIPanGestureRecognizer.maximumNumberOfTouches not respected in nested scroll views?

I have a root UIScrollView that only scrolls vertically, this scrollview represents rows in my jagged grid. I have configured this scroll view's pan gesture recognizer for two touches for both minimum and maximum number of touches requires.
Inside this scrollview I have one or more UIScrollView instances that only scrolls horizontally, these scrollviews each represent a single row in my jagged grid view. I have configured the pan gesture recognizers for all of these scroll views for one touch minimum, and two touches maximum.
So far it works, I get a nice jagged grid view where I can scroll vertically between rows, and horizontally to scroll each row independently. I have intentionally set to minimum number of touches as 2, as not to inter fear with scrolling if I add fro example a UITableView as a subview for any of cell within this jagged grid view (cell == a position defined by a row and column in that row).
Using a UITableView as a cell works, the table view works as expected that is. But scrolling with two fingers also scrolls inside the table view, not at the root scroll view for vertically scrolling between rows.
I have tried configuring the table views pan gesture recognizer to allow a maximum of one touches, in hope that two finger touches would be ignored. This does not work, the maximumNumberOfTouches property of the table view's pan gesture recognizer seams to be ignored.
What could I have done wrong?
A screen shot displaying the layout to clarify what I have done:
Multiple scrolling tends to get tricky, and I don't for sure, but I think Apple does not encourage this. Even so, I still think it's possible. It may be that vertical scrolling on the table view gets mixed with the scroll view vertical scrolling or something else.
Try checking if the delegates for the gesture recognizers are correctly set.
Another way around this is:
- having a Scroll view with buttons, from which you can open popovers with custom controllers (insert there whatever you want).
- create a big UITableViewController and setting the cell's contents as scrollviews etc. I think you could get the same result.
My advice is not to get stuck on just one method, when there could be others more simpler and more intuitive.
TableViews on Scroll views are generally not a great idea. When a TableView receives the touches, even if doesn't need to do anything with it, it won't send them to it's superView.
You might wanna try either of these 2 things:
In your TableView you should send the touches to your superView manually and let them handle them appropriately. I've seen this method being used in one of my side-projects but I'm not able to post an example of it at this time.
The second thing might be easier to implement. Since TableView is a subclass of ScrollView you can call upon the delaysContentTouches of those TableViews. This property will delay the touch-down even on that TableView until it can determine if scrolling is the intent, as is written in the AppleDocs: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIScrollView_Class/Reference/UIScrollView.html#//apple_ref/occ/cl/UIScrollView
Let me know if either of the 2 ways works for you, I'm quite curious about this subject generally.
But don't you try some tricks rather than implementing all such changes :
1) By Default, disable the scrolling of the TableView when the view is created.
2) Once the view gets generated, Recognize the gestures whether its Scrolling using single or multiple touches, if user touch the Child Scrollview.Look out the tag ,based on gestures, you can enable the Scrolling of Tableview.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//Get the tag of ScrollView
// Check for the Parent as well as Child SCrollview.
// If its child, just enable the scrolling of tableView.
}
- (void)tapAction:(UIGestureRecognizer *)gestureRecognizer
{
// CGPoint *poit = [Tile locationInView:gestureRecognizer.view];
/// [[[gestureRecognizers.view] objectAtIndex:0] removeFromSuperview];
// imageContent = [[UIImageView alloc]initWithFrame:CGRec tMake(0, 0, 200, 250)];
// [imageContent setImage:[UIImage imageNamed:#"Default.png"]];
NSLog(#"You tapped # this :%d",gestureRecognizer.view.tag);
//Regonize the gestures
}
There may be some unnecessary code since, there is no code snippet with your question.I gave a try & showed a trick if that could work for you & solve the problem. ;)
Try this link and pay attention to how they solve nested views.
Remember the best Practices for Handling Multitouch Events:
When handling events, both touch events and motion events, there are a few recommended techniques and patterns you should follow.
Always implement the event-cancellation methods.
In your implementation, you should restore the state of the view to what it was before the current multitouch sequence, freeing any transient resources set up for handling the event. If you don’t implement the cancellation method your view could be left in an inconsistent state. In some cases, another view might receive the cancellation message.
If you handle events in a subclass of UIView, UIViewController, or (in rare cases) UIResponder,
You should implement all of the event-handling methods (even if it is a null implementation).
Do not call the superclass implementation of the methods.
If you handle events in a subclass of any other UIKit responder class,
You do not have to implement all of the event-handling methods.
But in the methods you do implement, be sure to call the superclass implementation. For example,
[super touchesBegan:theTouches withEvent:theEvent];
Do not forward events to other responder objects of the UIKit framework.
The responders that you forward events to should be instances of your own subclasses of UIView, and all of these objects must be aware that event-forwarding is taking place and that, in the case of touch events, they may receive touches that are not bound to them.
Custom views that redraw themselves in response to events should only set drawing state in the event-handling methods and perform all of the drawing in the drawRect: method.
Do not explicitly send events up the responder (via nextResponder); instead, invoke the superclass implementation and let the UIKit handle responder-chain traversal.

Resources