Find Clicked UIImageview From UITapGestureRecognizer - ios

I attached events to my UIImageViews with UITapGestureRecognizer
override func viewDidLoad() {
super.viewDidLoad()
let cupPicture1Tap = UITapGestureRecognizer(target:self, action:Selector("imageTapped:"))
cupPicture1.userInteractionEnabled = true
cupPicture1.addGestureRecognizer(cupPicture1Tap)
let cupPicture2Tap = UITapGestureRecognizer(target:self, action:Selector("imageTapped:"))
cupPicture2.userInteractionEnabled = true
cupPicture2.addGestureRecognizer(cupPicture2Tap)
let cupPicture3Tap = UITapGestureRecognizer(target:self, action:Selector("imageTapped:"))
cupPicture3.userInteractionEnabled = true
cupPicture3.addGestureRecognizer(cupPicture3Tap)
}
func cupImageTapped(recognizer:UIPanGestureRecognizer) {
var clickedImageView: UIImageView = recognizer.view
let myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType = UIImagePickerControllerSourceType.Camera
myPickerController.allowsEditing = true
self.presentViewController(myPickerController, animated: true, completion: nil)
}
But i can't access which UIImageView clicked at cupImageTapped function. I am getting: "Cannot convert value of type 'UIView?' to specified type 'UIImageView'"

#IBOutlet var imageView: UIImageView!
#IBOutlet var MyImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// create tap gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: "tapGesture:")
// add it to the image view;
imageView.addGestureRecognizer(tapGesture)
// make sure imageView can be interacted with by user
imageView.userInteractionEnabled = true
}
func tapGesture(gesture: UIGestureRecognizer) {
// if the tapped view is a UIImageView then set it to imageview
if let imageView = gesture.view as? UIImageView { // if you subclass UIImageView, then change "UIImageView" to your subclass
// change the image on the MyImageView
MyImageView.image = imageView.image
// if you subclass UIImageView, then you could get the filename here.
}
}
This will work

You need to cast it to UIImageView
if var clickedImageView = recognizer.view as? UIImageView{
//Use clickedImageView here
}

Related

Subview containing UITextfield isn't registering tapgesture

I have a subview with a textfield. I'd like the keyboard to be dismissed when I tap anywhere outside of the textfield, but the problem is that taps within the subview aren't being registered and only taps outside of the subview dismiss the keyboard.
My view has a subview (coverView):
var coverView: UIView = {
let cover = UIView()
cover.translatesAutoresizingMaskIntoConstraints = false
cover.backgroundColor = .white
cover.widthAnchor.constraint(equalToConstant: 300).isActive = true
cover.heightAnchor.constraint(equalToConstant: 300).isActive = true
cover.clipsToBounds = true
return cover
}()
This coverView has its own ImageView:
var coverImageView: UIImageView = {
let imageView = UIImageView(image: nil)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = .white
imageView.contentMode = .scaleAspectFill
imageView.isUserInteractionEnabled = true
return imageView
}()
The coverView has a UITextfield added to it when tapped:
#objc func imageTapped(_ sender: UITapGestureRecognizer) {
guard self.textfield1.text == "" else {return}
self.coverView.addSubview(textfield1)
self.textfield1.centerXAnchor.constraint(equalTo: self.coverView.centerXAnchor).isActive = true
self.textfield1.centerYAnchor.constraint(equalTo: self.coverView.centerYAnchor).isActive = true
self.textfield1.becomeFirstResponder()
}
If the user taps anywhere I'd like the keyboard to dismiss. I do this using the following code:
#objc func keyboardDidShow() {
let exitTapGesture = UITapGestureRecognizer(target: self, action: #selector(exitKeyboardTap(_:)))
exitTapGesture.name = "exitTap"
exitTapGesture.delegate = self
self.view.addGestureRecognizer(exitTapGesture)
}
However, the keyboard only dismisses when I tap outside of the coverView. When I tap anywhere inside of the coverView the keyboard does not dismiss.
Try to add gesture to coverView
private func getTapGesture() -> UITapGestureRecognizer {
let exitTapGesture = UITapGestureRecognizer(target: self, action: #selector(exitKeyboardTap(_:)))
exitTapGesture.delegate = self
return exitTapGesture
}
#objc func keyboardDidShow() {
coverView.addGestureRecognizer(getTapGesture())
self.view.addGestureRecognizer(getTapGesture())
}

how to enable swipe gestures on imageview when it is embedded in scroll view

in this I had implemented the swipe gestures on image view and it is embedded in scroll view but gestures are not working here is my code any solution for this ?
collectionView.delegate = self
collectionView.dataSource = self
imageView.isUserInteractionEnabled = true
let swipeLeft = UISwipeGestureRecognizer(target: self, action:#selector(swiped(gesture:)))
swipeLeft.direction = .left
self.imageView.addGestureRecognizer(swipeLeft)
swipeLeft.cancelsTouchesInView = false
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiped(gesture:)))
swipeRight.direction = .right
self.imageView.addGestureRecognizer(swipeRight)
swipeRight.cancelsTouchesInView = false
imageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(imageTapped(_:)))
self.imageView.addGestureRecognizer(tap)
If you want swipe and scrolling both at work concurrently you have to implement gesture recognizer delegate.
// here are those protocol methods with Swift syntax
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
May be you could try this.Don't forget to delegate as self. :)
For your case, you want to have UI like Gallery View. Just Left and right swipe to change photo and tap/DoubleTap to zoom.
Don't need Swipe Gestures.
Just use Collection view with paging enabled. Each cell will display a single image. when Paging enabled, only a single cell will be shown at a time.
So just enable Paging enabled in collection view and try running.
If you want to zoom, when tapping a cell then, add TapGesture to CollectionView's parent UIScrollView and do write actions correspondingly.
For this case, I've used custom collection view cell.
I've just added my custom cell code for your reference as given below.
class ImageViewerCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
override func awakeFromNib() {
super.awakeFromNib()
self.scrollView.minimumZoomScale = 1.0
self.scrollView.maximumZoomScale = 6.0
self.scrollView.delegate = self
self.scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
self.scrollView.zoom(to: CGRect(origin: CGPoint.zero, size: scrollView.frame.size), animated: true)
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doubleTapAction(_:)))
doubleTap.numberOfTapsRequired = 2
self.scrollView.addGestureRecognizer(doubleTap)
}
func setURL(imageURL : URL, needLoader : Bool) {
DispatchQueue.main.async {
self.scrollView.setZoomScale(self.scrollView.minimumZoomScale, animated: true)
self.scrollView.zoom(to: CGRect(origin: CGPoint.zero, size: self.scrollView.frame.size), animated: true)
if needLoader {
self.activityIndicator.isHidden = false
self.activityIndicator.startAnimating()
self.imageView.pin_setImage(from: imageURL, completion: { (completed) in
self.activityIndicator.stopAnimating()
self.activityIndicator.isHidden = true
})
}
else {
self.activityIndicator.isHidden = true
self.imageView.pin_setImage(from: imageURL, placeholderImage: placeHolderImage)
}
self.imageView.pin_updateWithProgress = true
}
}
#IBAction func doubleTapAction(_ sender: Any) {
if scrollView.zoomScale == scrollView.minimumZoomScale {
let touchPoint = (sender as! UITapGestureRecognizer).location(in: scrollView)
let scale = min(scrollView.zoomScale * 3, scrollView.maximumZoomScale)
let scrollSize = scrollView.frame.size
let size = CGSize(width: scrollSize.width / scale,
height: scrollSize.height / scale)
let origin = CGPoint(x: touchPoint.x - size.width / 2,
y: touchPoint.y - size.height / 2)
scrollView.zoom(to:CGRect(origin: origin, size: size), animated: true)
}
else {
scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
scrollView.zoom(to: CGRect(origin: CGPoint.zero, size: scrollView.frame.size), animated: true)
}
}
}
extension ImageViewerCollectionViewCell : UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.imageView
}
}
As given above, I've used a imageview inside UIScrollView. So when you double tapped that scroll view, scrollview will zoom in & out.
Hope you understand and hope it helps for sure.

How to hide navigation bar when image is tapped

How would I hide the navigation bar once my imageView is tapped, the navigation bar messes up the view of the full screen image once my imageView is tapped and I would like it hidden when the image is tapped and to reappear once the image is dismissed. Here is my code for my image being tapped.
//expandImage
#IBAction func expand(_ sender: UITapGestureRecognizer) {
let imageView = sender.view as! UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = .black
newImageView.contentMode = .scaleAspectFit
newImageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreen))
newImageView.addGestureRecognizer(tap)
self.view.addSubview(newImageView)
}
func dismissFullscreen(_ sender: UITapGestureRecognizer) {
sender.view?.removeFromSuperview()
}
Add this to your expand() method:
self.navigationController?.setNavigationBarHidden(true, animated: true)
And in dismissFullscreen() method:
self.navigationController?.setNavigationBarHidden(false, animated: true)
Or you can create new ViewController, pass image to it (with segue e.g) and add this to viewDidLoad() of new ViewController:
self.navigationController?.hidesBarsOnTap = true
So here is how you can do that:
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let tapImageScrollView = UITapGestureRecognizer(target: self, action: #selector(imageTapped(_:)))
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapImageScrollView)
}
func imageTapped(_ sender: UIGestureRecognizer) {
if self.navigationController?.navigationBar.isHidden == false {
self.navigationController?.navigationBar.isHidden = true
} else {
self.navigationController?.navigationBar.isHidden = false
}
}
}
So basically add a UITapGestureRecognizer to your imageView and in the imageTapped function you check if the navigationBar is not hidden then you want to show the image and hide the navigationBar and if you click on the imageView again you want to show the navigationBar again.
So simply add the logic in imageTapped to your dismissFullscreen function.

UIImageView UITapGestureRecognizer not working

Tap gesture event not gettint called. I may be doing something wrong, but please have a look (I tried adding recognizer to self.view but still no luck) :
LoginViewController
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let container = UIView()
container.heightAnchor.constraintEqualToConstant(50).active = true
let myVC1 = MyViewController()
let myVC2 = MyViewController()
let myVC3 = MyViewController()
let myVC4 = MyViewController()
let myStackView = UIStackView(arrangedSubviews: [myVC1.view, myVC2.view, myVC3.view, myVC4.view])
myStackView.spacing = 10
myStackView.alignment = .Fill
myStackView.distribution = .EqualSpacing
container.addSubview(myStackView)
view.addSubview(container)
}
}
MyViewController
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
let ImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
ImageView.backgroundColor = UIColor.blueColor()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(pressedSocialMediaItem(_:)))
tapGestureRecognizer.delegate = self
tapGestureRecognizer.numberOfTapsRequired = 1
ImageView.userInteractionEnabled = true
ImageView.addGestureRecognizer(tapGestureRecognizer)
view.addSubview(ImageView)
}
func pressedSocialMediaItem(sender : UITapGestureRecognizer) {
print("PRESSED ! ")
}
}
I suggest using MyViewController.pressedSocialMediaItem, so your code should work like this.
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
let ImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
ImageView.backgroundColor = UIColor.blueColor()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyViewController.pressedSocialMediaItem(_:)))
tapGestureRecognizer.delegate = self
tapGestureRecognizer.numberOfTapsRequired = 1
ImageView.userInteractionEnabled = true
ImageView.addGestureRecognizer(tapGestureRecognizer)
view.addSubview(ImageView)
}
func pressedSocialMediaItem(sender : UITapGestureRecognizer) {
print("PRESSED ! ")
}
}
I have tested the following on my machine and it works:
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView.backgroundColor = UIColor.blueColor()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.pressedSocialMediaItem(_:)))
tapGestureRecognizer.delegate = self
tapGestureRecognizer.numberOfTapsRequired = 1
imageView.userInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
view.addSubview(imageView)
}
func pressedSocialMediaItem(sender : UITapGestureRecognizer) {
print("PRESSED ! ")
}
}
Okey, so I got it working somehow. All I need to do was to add view controllers inside my LoginViewController like so:
self.addChildViewController(myVC1)
Instead of using view.addSubview(container)
Notice: I'm not sure it is the correct way of doing this, and please comment if it's not. Meanwhile it solves my problem.

Swift, UILongPressGestureRecognizer Not working in UIlabel

I am trying long press Gesture in Swift for Copy Option.
But it is not working. It is not identifying the Gesture in UiView Or UILabel either.
Below is my Code
In View DidLoad
let copyLongPress = UILongPressGestureRecognizer(target: self, action: #selector(ContactDetailController.handleLongPress(_:)))
copyLongPress.numberOfTouchesRequired = 0
copyLongPress.delegate = self
copyLongPress.minimumPressDuration=0.5
self.lblDynaMobile.addGestureRecognizer(copyLongPress)
self.lblDynaMobile.userInteractionEnabled = true
self.lblDynaDDI.addGestureRecognizer(copyLongPress)
self.lblDynaDDI.userInteractionEnabled = true
self.GeneralView.addGestureRecognizer(copyLongPress)
self.EmailView.addGestureRecognizer(copyLongPress)
self.AddressView.addGestureRecognizer(copyLongPress)
New Mothod
func handleLongPress(longPressView :UILongPressGestureRecognizer) {
let lblFont:UILabel = (longPressView.view as? UILabel)!
UIPasteboard.generalPasteboard().string = lblFont.text
}
I have added UIGestureRecognizerDelegate too in the Declaration of class
Try this, and see (it's working.)
// in viewDidLoad()
let copyLongPress = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:)))
self.lblDynaMobile.addGestureRecognizer(copyLongPress)
func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
if let lblFont = gesture.view as? UILabel {
//UIPasteboard.generalPasteboard().string = lblFont.text
}
}

Resources