Detect UIImageView Touch in Swift
You can put an UITapGestureRecognizer
inside your UIImageView
using Interface Builder or in code (as you want), I prefer the first. Then you can put an @IBAction
and handle the tap inside your UIImageView
, Don't forget to set the UserInteractionEnabled
to true
in Interface Builder or in code.
@IBAction func imageTapped(sender: AnyObject) {
println("Image Tapped.")
}
I hope this help you.
How to get touch location when clicking a UIImageView?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: imageView)
print(position.x)
print(position.y)
}
}
How to detect touches on UIImageView of UITableViewCell in Swift?
Try writing it yourself. That is how you learn. Here are some line by line hints:
1: cell.imageView.userInteractionEnabled = YES;
2: cell.imageView.tag = indexPath.row;
3: UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myFunction:)];
4: tapped.numberOfTapsRequired = 1;
5: [cell.imageView addGestureRecognizer:tapped];
6: [tapped release];
7: -(void)myFunction :(id) sender
8: {
9: UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
10: NSLog(@"Tag = %d", gesture.view.tag);
11:}
Hints
- Lose the semicolons all around
- Line 1) Swift uses
true
instead ofYES
for a positiveBoolean
- Line 3) Type
let tapped = UITapGestureRecognizer(
into Xcode and look at the choices that pop up for autocomplete. Chose the one withtarget
andaction
. Fill in targetself
and action"myFunction:"
- Line 4) Pretty much identical
- Line 5) Call
addGestureRecognizer(tapped)
oncell.imageView
- Line 6) Not needed, ARC does this for you
- Line 7) Define a function
myFunction
that takes aUITapGestureRecognizer
calledgesture
and doesn't return anything - Line 9) Line not needed since you already took care of that in the header of your function
- Line 10) Use
println
instead ofNSLog
and use string interpolation to print outgesture.view.tag
How to detect a tap on an UIImageView while it is in the process of animation?
You CANNOT do what you want using UITapGestureRecognizer
because it uses frame
based detection and detects if a touch was inside your view by checking against its frame..
The problem with that, is that animations already set the view's final frame before the animation even begins.. then it animates a snapshot of your view into position before showing your real view again..
Therefore, if you were to tap the final position of your animation, you'd see your tap gesture get hit even though your view doesn't seem like it's there yet.. You can see that in the following image:
https://i.imgur.com/Wl9WRfV.png
(Left-Side is view-hierarchy inspector)..(Right-Side is the simulator animating).
To solve the tapping issue, you can try some sketchy code (but works):
import UIKit
protocol AnimationTouchDelegate {
func onViewTapped(view: UIView)
}
protocol AniTouchable {
var animationTouchDelegate: AnimationTouchDelegate? {
get
set
}
}
extension UIView : AniTouchable {
private struct Internal {
static var key: String = "AniTouchable"
}
private class func getAllSubviews<T: UIView>(view: UIView) -> [T] {
return view.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(view: subView) as [T]
if let view = subView as? T {
result.append(view)
}
return result
}
}
private func getAllSubviews<T: UIView>() -> [T] {
return UIView.getAllSubviews(view: self) as [T]
}
var animationTouchDelegate: AnimationTouchDelegate? {
get {
return objc_getAssociatedObject(self, &Internal.key) as? AnimationTouchDelegate
}
set {
objc_setAssociatedObject(self, &Internal.key, newValue, .OBJC_ASSOCIATION_ASSIGN)
}
}
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let touchLocation = touch.location(in: self)
var didTouch: Bool = false
let views = self.getAllSubviews() as [UIView]
for view in views {
if view.layer.presentation()?.hitTest(touchLocation) != nil {
if let delegate = view.animationTouchDelegate {
didTouch = true
delegate.onViewTapped(view: view)
}
}
}
if !didTouch {
super.touchesBegan(touches, with: event)
}
}
}
class ViewController : UIViewController, AnimationTouchDelegate {
@IBOutlet weak var myImageView: UIImageView!
deinit {
self.myImageView.animationTouchDelegate = nil
}
override func viewDidLoad() {
super.viewDidLoad()
self.myImageView.isUserInteractionEnabled = true
self.myImageView.animationTouchDelegate = self
}
func onViewTapped(view: UIView) {
print("Works!")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
myImageView.center.y += view.bounds.height
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 5, delay: 0, options: [.repeat, .autoreverse, .allowUserInteraction], animations: {
self.myImageView.center.y -= self.view.bounds.height
})
}
}
It works by overriding touchesBegan on the UIView
and then checking to see if any of the touches landed inside that view.
A MUCH better approach would be to just do it in the UIViewController
instead..
import UIKit
protocol AnimationTouchDelegate : class {
func onViewTapped(view: UIView)
}
extension UIView {
private class func getAllSubviews<T: UIView>(view: UIView) -> [T] {
return view.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(view: subView) as [T]
if let view = subView as? T {
result.append(view)
}
return result
}
}
func getAllSubviews<T: UIView>() -> [T] {
return UIView.getAllSubviews(view: self) as [T]
}
}
class ViewController : UIViewController, AnimationTouchDelegate {
@IBOutlet weak var myImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.myImageView.isUserInteractionEnabled = true
}
func onViewTapped(view: UIView) {
print("Works!")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
myImageView.center.y += view.bounds.height
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 5, delay: 0, options: [.repeat, .autoreverse, .allowUserInteraction], animations: {
self.myImageView.center.y -= self.view.bounds.height
})
}
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let touchLocation = touch.location(in: self.view)
var didTouch: Bool = false
for view in self.view.getAllSubviews() {
if view.isUserInteractionEnabled && !view.isHidden && view.alpha > 0.0 && view.layer.presentation()?.hitTest(touchLocation) != nil {
didTouch = true
self.onViewTapped(view: view)
}
}
if !didTouch {
super.touchesBegan(touches, with: event)
}
}
}
How to detect touches on UIImageView of UITableViewCell object in the UITableViewCellStyleSubtitle style
In your cellForRowAtIndexPath
method add this code
cell.imageView.userInteractionEnabled = YES;
cell.imageView.tag = indexPath.row;
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myFunction:)];
tapped.numberOfTapsRequired = 1;
[cell.imageView addGestureRecognizer:tapped];
[tapped release];
And then to check which imageView
was clicked, check the flag in selector
method
-(void)myFunction :(id) sender
{
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
NSLog(@"Tag = %d", gesture.view.tag);
}
Touch up and Touch down action for UIImageView
Here is the solution:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
if touch.view == self {
//began
}
}
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
if touch.view == self {
//end
}
}
super.touchesEnded(touches, with: event)
}
Note: Put this inside a UIView SubClass and add: userInteractionEnabled = true
inside the init block
UIImageView does not recognize my tap events
The UIImageView
is by default set to have the isUserInteractionEnabled
property to false
, that means that you can´t interact with the UIImageView
.
Add this property and it will work:
imageView.isUserInteractionEnabled = true
Related Topics
Swiftui Buttonstyle - How to Check If Button Is Disabled or Enabled
How to Get the MAC Os X Firewall to Permanently Allow My iOS App
Leaving Inputaccessoryview Visible After Keyboard Is Dismissed
Set Different Activity Items for Uiactivityviewcontroller Swift
How to Play Movie with a Url Using a Custom Nsurlprotocol
Collectionview with the Horizontal Scroll with Mulitple Section
Swift - Must Call a Designated Initializer of the Superclass Skspritenode Error
Installed App from Testflight Crashes Due to Alleged Uisearchdisplaycontroller
View Controller Responds to App Delegate Notifications in iOS 12 But Not in iOS 13
How to Control Hardware Mic Input Gain/Level on Iphone
How to Draw Inside the Black Edges in iOS Sdk with Opengl Es
iOS Crash When Testing on Device - Debug Logs
Link to Safari "Add to Home Screen" from Inside App
How to Pop View Controller to One of the Previous View Controllers in Swift