Adding LongPressGestureRecognizer to UITableViewCell - ios

I have a custom UITableView cell and I want to add a long press gesture recognizer to it. Currently, I'm doing it as so:
longPressGesture.minimumPressDuration = 1.0
longPressGesture.addTarget(self, action: "testFeedback")
cell.addGestureRecognizer(longPressGesture)
I'm doing it programmatically because I could not find a good way to detect which cell was tapped within an IBAction. However, I'm having a hard time getting this to work I want to pass a parameter through the selector. I am not opposed to doing this in storyboards, but would appreciate some guidance on it.
Thanks!

testFeedback function should look like this
func testFeedback(gestureRecognizer:UIGestureRecognizer) {
if (gestureRecognizer.state == UIGestureRecognizerState.Ended) {
var point = gestureRecognizer.locationInView(self.tableView)
if let indexPath = self.tableView.indexPathForRowAtPoint(point)
{
println(indexPath.row) /// long press ended
}
}
else if (gestureRecognizer.state == UIGestureRecognizerState.Began){
/// long press started
}
}

Related

Pan gesture in UITableViewCell prevents scrolling in UITableView. How to fix it?

I have got an UITableView with a custom TableViewCell. I use a pan gesture for recognizing the positions while moving my finger to the left and to the right. On basis of the finger position I change some values in the labels in this TableViewCell. This works really great. But suddenly I can not scroll the TableView up and down. I already read the reason. Swift can not work with two gesture recognizers at the same time. And I found many examples of people how have nearly the same problem. I tried many of them but I can not fix my problem. I use Swift 5. Could you please describe a bit more precise how to fix my problem? Many thanks
import UIKit
class TVCLebensmittel: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
self.addGestureRecognizer(gestureRecognizer)
}
#IBAction func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
if gestureRecognizer.state == .began {
let translation = gestureRecognizer.translation(in: self)
// Put my finger on the screen
} else if gestureRecognizer.state == .changed {
let translation = gestureRecognizer.translation(in: self)
// While moving my finger ...
} else if gestureRecognizer.state == .ended {
let translation = gestureRecognizer.translation(in: self)
// Lift finger
}
}
...
}
The solution is to insert the pan gesture to the tableview and not to the tableviewcell. So I can listen to the left and right pan and also the up and down movement of the tableview.
I just share my approach. link It works very well. I needed custom swipe design while perform delete. Try it. If you need more information feel free to ask. Check it if you like.
This gestureRecognizerShouldBegin let you to use scroll while using UIPanGestureRecognizer.
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if (gestureRecognizer.isKind(of: UIPanGestureRecognizer.self)) {
let t = (gestureRecognizer as! UIPanGestureRecognizer).translation(in: contentView)
let verticalness = abs(t.y)
if (verticalness > 0) {
print("ignore vertical motion in the pan ...")
print("the event engine will >pass on the gesture< to the scroll view")
return false
}
}
return true
}

UITableView single-gesture row swipe actions

I'm trying to implement single-gesture swiping actions in my UITableView, where you swipe to reveal action buttons, and continue swiping all the way across to activate the default action (such as "Delete" or "Mark as Read" in Mail).
I'm implementing -tableView:editActionsForRowAtIndexPath: in my delegate. My button appears, and it works when I tap it, but it doesn't get activated by a full swipe.
I've tried it with and without -tableView:commitEditingStyle:forRowAtIndexPath: and -tableView:canEditRowAtIndexPath: in my data source. Only the latter gets called, but neither seems to make a difference.
Is there something more I need to do? Or is this behavior not actually achievable using the standard API?
I would check to see if the swipe has past a certain threshold in your gesture recognizer's target function.
Try this
func swipeRight(sender: UIGestureRecognizer){
let threshold : CGFloat = 100;
var startLocation = CGPoint()
if (sender.state == UIGestureRecognizerState.Began){
startLocation = sender.locationInView(self.view)
}else if (sender.state == UIGestureRecognizerState.Ended){
let stopLocation = sender.locationInView(self.view)
let distanceX = stopLocation.x - startLocation.x
let distanceY = stopLocation.y - startLocation.y
let distance = sqrt(distanceX*distanceX + distanceY*distanceY )
if (distance > threshold ){
//Delete or Edit Row Here
}
}
}

In swift, how do I detect when a press begins and end on a UILabel?

I want to be able to detect when a press begins so I can perform an action while it is pressed only, stopping that action when press ends.
I know there is a pressesBegan function on UILabels but I am not sure how to use it and can't seem to find examples.
You can use UILongPressGestureRecongizer.
Initialize the pressGestureRecongizer in the viewDidLoad method of your viewController and add it to the label:
let pressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handlePress:")
label.addGestureRecognizer(pressGestureRecognizer)
and then you define the handlePress-function
func handlePress(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizerState.Began {
// handle start of pressing
}
else if sender.state == UIGestureRecognizerState.Ended {
// handle end of pressing
}
}

How to pass indexPath.row of the dragged cell into a function? (SWIFT)

Currently, I have a tableview with different "user profile pictures" populating each cell. As you drag the picture past a certain point horizontally, it triggers another function. This is done with UIPanGestureRecogniser.
My problem is, how do I pass the indexPath.row of the dragged image into the function, so the function knows which "user" to work with? Right now it has no way of knowing which cell was dragged.
If someone could outline the general direction of how this can be done I would be very grateful!
This could work:
In cellForRowAtIndexPath, set the tag property of your image to the row number.
// something like this
let pan = UIPanGestureRecognizer(target: self, action: "handlePan:")
cell.image.addGestureRecognizer(pan)
cell.image.tag = indexPath.row
In the handler for the pan:
func handlePan(recognizer: UIPanGestureRecognizer) {
if let row = recognizer.view?.tag {
// use row number
println("row number is \(row)")
}
}

How to detect tap gesture on chart marker?

I am using Charts to create custom graphs in an application. The one thing I am having trouble with is detecting touch events on the chart marker that is presented for the current value. I want to perform and action based on the marker that was tapped. The action should take in the data entry represented by the tapped marker.
I have read through Selectable marker view & images at Y axis, but still haven't been able to produce a viable solution.
It would be great if someone could provide a code sample, or more detailed explanation than found in the link above, to point me in the right direction.
Thanks
As per your requirement Charts library already have that method in its delegate.
Please check below code :
Assign delegate to your ChartView like below
lineChartView.delegate = self
Implement Delegate method in your class
public func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
}
Here you can write your code while user click on chart.
Hope this info will helps!
I ended up solving this by subclassing the ChartView of my choice and overriding the existing tap gesture recognizer with my own.
Example
final class CustomChartView: BarChartView {
...
private func initialize() {
...
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.addGestureRecognizer(tap)
}
#objc func tapRecognized(_ recognizer: UITapGestureRecognizer) {
guard data !== nil else { return }
switch recognizer.state {
case .ended:
// Detect whether or not the touch was inside a marker that was being presented
// Otherwise, add/remove highlight as necessary
if let marker = self.marker as? BalloonMarker {
let location = recognizer.location(in: self)
if !highlighted.isEmpty && marker.rect.contains(location) {
// In my case, I created custom property 'vertex' on BalloonMarker for easy reference to get `xValue`
let xValue = self.getTransformer(forAxis: .left).valueForTouchPoint(marker.vertex).x
// Do what you need to here with tap (call function, create custom delegate and trigger it, etc)
// In my case, my chart has a marker tap delegate
// ex, something like: `markerTapDelegate?.tappedMarker()`
return
}
}
// Default tap handling
guard isHighLightPerTapEnabled else { return }
let h = getHighlightByTouchPoint(recognizer.location(in: self))
if h === nil || h == self.lastHighlighted {
lastHighlighted = nil
highlightValue(nil, callDelegate: true)
} else {
lastHighlighted = h
highlightValue(h, callDelegate: true)
}
default:
break
}
}

Resources