Transfer gestures on a UIView to a UITableView in Swift - iOS
That's Tricky
What is problem ?
Your top view is not allowed to pass through view behind it...
What would be possible solutions
- pass all touches to view behind it (Seems to not possible or very tough practically )
- Tell window to ignore touches on top view (Easy one)
Second option is better and easy.
So What you need to do is create subclass of UIView
and override
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
and return nil if you found same view on hitTest
action
Here Tested and working example
class PassThroughME : UIView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
return super.hitTest(point, with: event) == self ? nil : self
}
}
That's it now use PassThroughME
either by adding class to your view in storyboard or programmatically whatever way you have added your view
Check image i have black color view with 0.7 alpha on top still i am able to scroll
Hope it is helpful
Passing vertical scrolling gesture to UITableView below
I just solved a similar problem, except it was for vertical pans instead of horizontal ones. I'm not 100% sure about your use case, so this may not be what your looking for, but it may lead you in the right direction.
I sub-classed UIPanGestureRecognizer, and implemented the touchesMoved method, and checked to see whether the gesture had a larger horizontal or vertical change. Below is a snippet. The credit belongs to a different stackoverflow post, but I cannot find the link at the moment. (Sorry in advance for the poor formatting, first time posting)
-(void)touchesMoved:(NSSet*) touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if(self.state == UIGestureRecognizerStateFailed) return;
CGPoint currentPoint = [[touches anyObject] locationInView:self.view];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view];
moveX += prevPoint.x - currentPoint.x;
moveY += prevPoint.y - currentPoint.y;
if(!drag) {
if(abs(moveY) > abs(moveX))
drag = YES;
else
self.state = UIGestureRecognizerStateFailed;
}
}
-(void)reset
{
[super reset];
drag = NO;
moveX = 0;
moveY = 0;
}
In my parent view controller, which I believe would be the UITableView in this case, I also implemented the following. I think in your case, you'd want to return no if it's a horizontal pan.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if([gestureRecognizer isKindOfClass:[VerticalPanGestureRecognizer class]])
{
return YES;
}
return NO;
}
Let me know if any of this is unclear.
Good Luck!
How to add gesture to UITableViewCell?
To add gesture to UITableViewCell, you can follow the steps below:
First, add gesture recognizer to UITableView
tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self
Then, define the selector. Use recognizer.locationInView
to locate the cell you tap in tableView. And you can access the data in your dataSource by tapIndexPath
, which is the indexPath of the cell the user tapped.
func tapEdit(recognizer: UITapGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.Ended {
let tapLocation = recognizer.locationInView(self.tableView)
if let tapIndexPath = self.tableView.indexPathForRowAtPoint(tapLocation) {
if let tappedCell = self.tableView.cellForRowAtIndexPath(tapIndexPath) as? MyTableViewCell {
//do what you want to cell here
}
}
}
}
It is possible to add gesture directly to TableView cell and access the datasource in viewController, You need to set up a delegate:
In your custom cell:
import UIKit
class MyTableViewCell: UITableViewCell {
var delegate: myTableDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MyTableViewCell.tapEdit(_:)))
addGestureRecognizer(tapGesture)
//tapGesture.delegate = ViewController()
}
func tapEdit(sender: UITapGestureRecognizer) {
delegate?.myTableDelegate()
}
}
protocol myTableDelegate {
func myTableDelegate()
}
In your viewController:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate, myTableDelegate {
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 35
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? MyTableViewCell
cell?.delegate = self
return cell!
}
func myTableDelegate() {
print("tapped")
//modify your datasource here
}
}
However, this method could cause problems, see UIGestureRecognizer and UITableViewCell issue. In this case, when the swipe gesture successes, the selector get called twice for some reason. I can't say the second method is a bad one as I haven't found any direct evidence yet, but after searching through Google, it seems like the first method is the standard way.
UITapGestureRecognizer breaks UITableView didSelectRowAtIndexPath
Ok, finally found it after some searching through gesture recognizer docs.
The solution was to implement UIGestureRecognizerDelegate
and add the following:
#pragma mark UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isDescendantOfView:autocompleteTableView]) {
// Don't let selections of auto-complete entries fire the
// gesture recognizer
return NO;
}
return YES;
}
That took care of it. Hopefully this will help others as well.
Related Topics
Xcode 9: Swift Dependency Analysis Error
Non-Main Bundle File as Alert Sound
Swift 3 Filter Array of Dictionaries by String Value of Key in Dictionary
How to Pass Values from a Pop Up View Controller to the Previous View Controller
Nsfilemanager Moveitem Throws Error Code=513
How to Change Status Bar Text Color Immediately in Swift in iOS 13
Dyld: Library Not Loaded: @Rpath/Mydsk.Framework/Mydsk -> Swift iOS 8.0
How to Change Pin Color in Mapkit Under the Same Annotationview (Swift3)
Scroll All the Way Down to the Bottom of Uitableview
How to Set Up Array for Multi Annotations with Swift
iOS Swift App with More Photos: Performance and Storage Suggestions
How to Pass a Swift Object to JavaScript (Wkwebview/Swift)
How to Convert a Persian Date into a Gregorian in Swift
Uibezierpath + Cashapelayer - Animate a Circle Filling Up
Facebook Sdk Login Throws Error in Swift 2 iOS 9
Check the JSON Response Is Array or Int or String for a Key
Making the Map Zoom to User Location and Annotation (Swift 2)