How to create just one tapGestureRecognizer for several UILabels? - ios

I am trying (and failing) to create just one tapGestureRecognizer to use on several UILabels.
Right now I am creating for every label in viewDidLoad a separate tapGestureRecognizer and adding it to the appropriate label. I ran into this problem because every touch should obviously call a different function.
This is how I create them:
#IBOutlet weak var buttonOne: UILabel!
#IBOutlet weak var buttonTwo: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//tapGestureRecognizer for buttonOne
buttonOne.isUserInteractionEnabled = true
let oneGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MainViewController.buttonOneAction))
buttonOne.addGestureRecognizer(oneGestureRecognizer)
//tapGestureRecognizer for buttonTwo
buttonTwo.isUserInteractionEnabled = true
let twoGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MainViewController.buttonTwoAction))
buttonTwo.addGestureRecognizer(twoGestureRecognizer)
...
They work fine, but how and where could I create just one tapGestureRecognizer and add it in viewDidLoad to each label with a different action?

Just create one per label.
The alternative is to create a single tap gesture recognizer that you attach to the common superview of all target views, and write a BUNCH of code that does hit-testing to figure out if the tap landed on any of your labels, and if so, which one, and dispatches the desired method for that label.
However, that's the whole point of tap gesture recognizers. You'd probably spend several days developing a bunch of code that has no benefits over using multiple tap gesture recognizers.

As already mentioned in comments by #Duncan C you can switch the gesture recognizer view as follow:
class ViewController: UIViewController {
#IBOutlet weak var buttonOne: UILabel!
#IBOutlet weak var buttonTwo: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
[buttonOne, buttonTwo].forEach {
$0?.isUserInteractionEnabled = true
$0?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapGesture)))
}
}
#objc func tapGesture(_ gesture: UITapGestureRecognizer) {
guard let label = gesture.view as? UILabel else { return }
switch label {
case buttonOne: print("buttonOne")
case buttonTwo: print("buttonTwo")
default: break
}
}
}

Related

Make UIImageView accessible from all viewControllers

My question is, how can I make it so redDot and wCircle can be accessed from the Second viewController so they can become hidden or not hidden. They are not connected directly, but you can get to them with different viewControllers.
First viewController
class SecondViewController: UIViewController
{
#IBOutlet weak var redDot: UIImageView!
#IBOutlet weak var wCircle: UIImageView!
}
Second viewController
class ProgressViewController: UIViewController {
#IBOutlet weak var rDot: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
rDot.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(rdotimageTapped(tapGestureRecognizer:)))
rDot.addGestureRecognizer(tapGestureRecognizer)
view.bringSubview(toFront: rDot)
}
func rdotimageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
wcircle.isHidden = true
redDot.isHidden = false
view.layoutIfNeeded()
print("It worked")
}
Im not sure if this is a right way but what I would do is have a reference of UIImageView in my second VC and then set that to the imageView of my first VC.
So add these two in your "ProgressViewController"
var redDot: UIImageView?
var wCircle: UIImageView?
and then in your prepare for segue pass your current UIImageView.
let progressViewController = segue.destination as! ProgressViewController
progressViewController.redDot = self.redDot
progressViewController.redDot.wCircle = self.wCircle
You can achieve that by adding a new member to your second and third view controllers, this member is a closure:
var updateFirstViewControllerImageViews: (() -> Void)?
Then override prepare for segue method of your firstViewController, and set updateFirstViewControllerImageViews for each of your second and third view controller like this:
secondViewController.updateFirstViewControllerImageViews = {
// Update your image views here in the way you want!
}
Now, in your second and third view controllers you can use that closure wherever you want like this:
self.updateFirstViewControllerImageViews?()

Tapping a view in xcode / swift 3 to 'select' it

I'm looking to hone in on the methodology used to 'select' UIViews by a single tap. In my UI, I have several UIViews that I would like to be 'selectable.' While selected, I will have controls to perform basic adjustments such as alpha (to let the user know which view is selected), and slightly more advanced functionality such as revealing a unique set of menu items. Only 1 view may be selected at a time. No multi-touch here.
The problem is, I've only seen this done with UICollectionViewCells. My interface isn't utilizing a collection view, so that's out of the question.
Thought process going into this is 1 tap gesture to 'select' the uiview, and then 'deselecting' it by tapping outside of the views bounds.
Another thought process is going with UIButtons instead of UIViews to utilize the Selected state.
Which would be the more viable solution here? Is this even possible using just UIViews? Or should I backtrack and go UIButtons instead?
Thanks.
You need to add a gesture recognizer to the desired UIView
class ViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.tap(_:)))
tap.delegate = self
myView.addGestureRecognizer(tap)
}
}
Then you need to add the Code to handle whatever happens to your UIView into the gesture recognizer function:
func tap(_ gestureRecognizer: UITapGestureRecognizer) {
myView.alpha = 0.5
}
This will change UIView's alpha property to 0.5 once the UIView gets selected.
Now you could for example put a second UIView with a gesture recognizer and play with the alphas:
class ViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var myView: UIView!
#IBOutlet weak var secondView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.tap(_:)))
tap.delegate = self
myView.addGestureRecognizer(tap)
let tap2 = UITapGestureRecognizer(target: self, action: #selector(self.tap2(_:)))
tap.delegate = self
secondView.addGestureRecognizer(tap2)
}
func tap(_ gestureRecognizer: UITapGestureRecognizer) {
myView.alpha = 0.5
secondView.alpha = 1
}
func tap2(_ gestureRecognizer: UITapGestureRecognizer) {
myView.alpha = 1
secondView.alpha = 0.5
}
}
That way, depending on the UIView you hit, the alpha will change...
Edit:
In this Code the UIViews will be "selected" - the alpha will change and will change back within a set timing of 0.8 seconds.
class ViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var myView: UIView!
#IBOutlet weak var secondView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.tap(_:)))
tap.delegate = self
myView.addGestureRecognizer(tap)
let tap2 = UITapGestureRecognizer(target: self, action: #selector(self.tap2(_:)))
tap.delegate = self
secondView.addGestureRecognizer(tap2)
}
func tap(_ gestureRecognizer: UITapGestureRecognizer) {
myView.alpha = 0.5
UIView.animate(withDuration: 0.8, animations: {
self.myView.alpha = 1
})
}
func tap2(_ gestureRecognizer: UITapGestureRecognizer) {
secondView.alpha = 0.5
UIView.animate(withDuration: 0.8, animations: {
self.secondView.alpha = 1
})
}
}

Double tap gesture function is being fired after 1 tap only on first tap, every other instance it requires 2 taps

As of right now, when I run my program and tap, I am getting the println() message after one tap. However, after the first println() message, I have to double tap for every following println() message.
I want it so every time I have to double tap (including the first time).
In my View Controller I have the following:
#IBOutlet weak var graphview: GraphView! {
didSet {
//
graphview.addGestureRecognizer(UITapGestureRecognizer(target: graphview, action: "doubleTap:"))
}
}
And my function in the View is the following:
func doubleTap(gesture: UITapGestureRecognizer)
{
gesture.numberOfTapsRequired = 2
println("hit twice")
}
You have to set
gesture.numberOfTapsRequired = 2
before adding the gesture recognizer to the view, i.e.
#IBOutlet weak var graphview: GraphView! {
didSet {
var doubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: graphview, action: "doubleTap:")
doubleTap.numberOfTapsRequired = 2
graphview.addGestureRecognizer(doubleTap)
}
}
and
func doubleTap(gesture: UITapGestureRecognizer)
{
println("hit twice")
}

Closed:: Creating a UIButton horizontal carousel with swipe and tap gestures

Inside of a VC, I'm trying to figure out how to have a UIButton recognize a horizontal swipe and then tap.
There is an array of text.
var plotList = ["stuff", "to do", "this", "or that"]
default display is plotList[0].
the carousel repeats in an infinite loop doesn't stop at the end of the array.
as user swipes over button only, i don't want the other components of the VC to react to this particular swipe, i want the button to display the plotList string.
when the user taps on the button, i want to shove the result into a switch that will launch the appropriate UIView.
i'd like to avoid doing this UILabel/UIButton combination. See Handling Touch Event in UILabel and hooking it up to an IBAction.
so far i'm here
import UIKit
class carouselVC: UIViewController {
#IBOutlet var carouselView: UIView!
#IBOutlet var labelOutlet: UILabel!
#IBOutlet var buttonOutlet: UIButton!
var plotList = ["stuff", "this", "that"]
let swipeRec = UISwipeGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
var swipeButtonLeft: UISwipeGestureRecognizer =
UISwipeGestureRecognizer(target: self, action: "buttonLeft")
swipeButtonLeft.direction = UISwipeGestureRecognizerDirection.Left
self.buttonOutlet.addGestureRecognizer(swipeButtonLeft)
var swipeButtonRight: UISwipeGestureRecognizer =
UISwipeGestureRecognizer(target: self, action: "buttonRight")
swipeButtonRight.direction = UISwipeGestureRecognizerDirection.Right
self.buttonOutlet.addGestureRecognizer(swipeButtonRight)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func buttonLeft(){
println("buttonLeft")
}
func buttonRight(){
println("buttonRight")
}
#IBAction func buttonAction(sender: UIButton) {
sender.setTitle(plotList[1], forState: .Normal)
}
}
any help?
Use a UIView with a UILabel, instead of button. Add UIView over UILabel and make it clear color. You may make UIlabel look like a button. Add a swipe gesture/tap gesture on it. And do any operation in the action of the gestures.

Adding gestures to a button in swift

I'm trying to add gesture(swipe) functionality to an existing button in my view but I can't figure out how to attach the swipe to the button's area.
The desired effect is to have a button I can press as well as swipe to produce different outcomes. So far the way I'm implementing gestures applies it to my entire view not just the button.
I have a feeling it's pretty simple but it's been escaping me for a couple of days - I might just be searching for the wrong thing.
(I'm assigning '#IBOutlet var swipeButton: UIButton!' to my button BTW)
Code below:
class ViewController: UIInputViewController {
#IBOutlet var swipeButton: UIButton!
let swipeRec = UISwipeGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
self.loadInterface()
var swipeButtonDown: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "ButtonDown")
swipeButtonDown.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipeButtonDown)
}
#IBAction func buttonPressed(sender: UIButton) {
var proxy = textDocumentProxy as UITextDocumentProxy
proxy.insertText("button")
}
func buttonDown(){
var proxy = textDocumentProxy as UITextDocumentProxy
proxy.insertText("swipe")
}
}
If you want to add swipeGesture into Button then do it like this way:
self.yourButton.addGestureRecognizer(swipeButtonDown)
and also there is a mistake in selector you sent it should be like:
var swipeButtonDown: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "buttonDown")
change ButtonDown to buttonDown

Resources