Detect Uiimageview Touch in Swift

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 of YES for a positive Boolean
  • Line 3) Type let tapped = UITapGestureRecognizer( into Xcode and look at the choices that pop up for autocomplete. Chose the one with target and action. Fill in target self and action "myFunction:"
  • Line 4) Pretty much identical
  • Line 5) Call addGestureRecognizer(tapped) on cell.imageView
  • Line 6) Not needed, ARC does this for you
  • Line 7) Define a function myFunction that takes a UITapGestureRecognizer called gesture 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 of NSLog and use string interpolation to print out gesture.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



Leave a reply



Submit