My question and code is based on this answer to one of my previous questions. I have programmatically created stackview where several labels are stored and I’m trying to make these labels clickable. I tried two different solutions:
-
Make clickable label. I created function and assigned it to the label in the gesture recognizer:
public func setTapListener(_ label: UILabel){ let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapGestureMethod(_:))) tapGesture.numberOfTapsRequired = 1 tapGesture.numberOfTouchesRequired = 1 label.isUserInteractionEnabled = true label.addGestureRecognizer(tapGesture) } @objc func tapGestureMethod(_ gesture: UITapGestureRecognizer) { print(gesture.view?.tag) }
but it does not work. Then below the second way….
-
I thought that maybe the 1st way does not work because the labels are in UIStackView so I decided to assign click listener to the stack view and then determine on which view we clicked. At first I assigned to each of labels in the stackview tag and listened to clicks:
let tap = UITapGestureRecognizer(target: self, action: #selector(didTapCard(sender:))) labelsStack.addGestureRecognizer(tap) .... @objc func didTapCard (sender: UITapGestureRecognizer) { (sender.view as? UIStackView)?.arrangedSubviews.forEach({ label in print((label as! UILabel).text) }) }
but the problem is that the click listener works only on the part of the stack view and when I tried to determine on which view we clicked it was not possible.
I think that possibly the problem is with that I tried to assign one click listener to several views, but not sure that works as I thought. I’m trying to make each label in the stackview clickable, but after click I will only need getting text from the label, so that is why I used one click listener for all views.
3
Answers
The problem is with the the stackView’s height. Once the label is rotated, the stackview’s height is same as before and the tap gestures will only work within stackview’s bounds.
I have checked it by changing the height of the stackview at the transform and observed tap gestures are working fine with the rotated label but with the part of it inside the stackview.
Now the problem is that you have to keep the bounds of the label inside the stackview either by changing it axis(again a new problem as need to handle the layout with it) or you have to handle it without the stackview.
You can check the observation by clicking the part of rotated label inside stackview and outside stackview.
Code to check it:
Applying a
transform
to a view (button, label, view, etc) changes the visual appearance, not the structure.Because you’re working with rotated views, you need to implement hit-testing.
Quick example:
Assuming you’re still working with the
MyCustomView
class and layout from your previous questions, we’ll build on that with a few changes for layout, and to allow tapping the labels.Complete example: