I am working with UIScrollView
and UIStackView
to scroll horizontally and select a UIControl
element.
I have addTarget set on a UIControl
element as follows inside a UIStackView
:
i.e HighlightColorView
is of type UIControl
lazy var colorsStackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.isUserInteractionEnabled = true
stackView.alignment = .center
stackView.spacing = 12
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.isUserInteractionEnabled = true
for color in colors {
let colorView = HighlightColorView()
colorView.backgroundColor = color
colorView.addTarget(self, action: #selector(self.handleColorTap(_:)), for: .touchUpInside)
stackView.addArrangedSubview(colorView)
}
return stackView
}()
@objc func handleColorTap(_ sender: UIView) {
highlightSelectionDelegate.didTapColor(colorView: sender, mainView: self)
let viewBackgroundColor = sender.backgroundColor ?? .black
print("🎯", viewBackgroundColor)
}
The issue is that when you tap on a colorView
which is of type UIControl
the tap doesn't work as expected. There seems to be a freeze and it only works when the view is dismissed.
Basically you tap on a color and nothing happens then when you dismiss the view then the tap registers and starts working.
It seems to be an issue with the scrollView but I am not sure.
Implementation of the scrollView
:
lazy var scrollView: UIScrollView = {
let scView = UIScrollView()
scView.contentInset = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
scView.showsHorizontalScrollIndicator = false
scView.translatesAutoresizingMaskIntoConstraints = false
scView.isUserInteractionEnabled = true
scView.delaysContentTouches = false
return scView
}()
The use case it to be able to scroll on colors and tap them to highlight a text.
One thing I noticed is that you may be referring to UITapGestureRecognizer
. if you are using UIGestureRecognizer
by itself then it won't work.
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleColorTap))
view.addGestureRecognizer(tapRecognizer)
To answer the question you asked
A UIGestureRecognizer
is to be used with a single view. answer by @TomSwift.
I think this applies in your case where you are using multiple views. set addTarget
or addGestureRecognizer
to only one view.
If you are using multiple view such as in your case where you have a UIControl
inside a UIStackView
and the UIStackView
inside a UIScrollView
you need to make sure that addTarget
or addGestureRecognizer
is only set to one of the views
only.
Since you want the UIControl
to respond to a tap you need to set addTarget
only on this view and not on the UIScrollView
and/or UIStackView
.
for color in colors {
let colorView = HighlightColorView()
colorView.backgroundColor = color
colorView.addTarget(self, action: #selector(handleColorTap(_:)), for: .touchUpInside)
colorsStackView.addArrangedSubview(colorView)
}
viewDidLoad
function, It is fine where it is. Just remove additional addTarget
or addGestureRecognizer
from your views.