I have a customSwitch UIView class, and inside that class, I am applying some tap and pan gestures on it. Now, I have made that class as a component, like I can reuse it anywhere, but the problem is that I am not able to get the pan and tap gestures of that custom switch if I declare that custom switch class anywhere else. My question is how do I access those tap and pan gestures? Thanks.
CustomSwitch.Swift
class CustomSwitch : UIView {
var minMaxButtonConstraint:CGFloat = 0
var buttonLeadingConstraint:NSLayoutConstraint!
var isSwitched = false
var tapGest = UITapGestureRecognizer()
var panGest = UIPanGestureRecognizer()
var button:UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.layer.cornerRadius = 6
btn.backgroundColor = .white
btn.imageView?.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5)
btn.addTarget(self, action: #selector(switchDirection), for: .touchUpInside)
return btn
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 10
self.backgroundColor = .switchGrey
setupViews()
}
func setupViews() {
addSubview(button)
declareGestureRecognizers()
NSLayoutConstraint.activate([
button.topAnchor.constraint(equalTo: self.topAnchor, constant: 4),
button.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -4),
button.widthAnchor.constraint(equalToConstant: 12),
])
// Taken these constraints separately so that a reference can be maintained to these constraints and can be changed when needed
buttonLeadingConstraint = button.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 4)
buttonLeadingConstraint.isActive = true
}
func declareGestureRecognizers() {
tapGest = UITapGestureRecognizer(target: self, action: #selector(CustomSwitch.tapped))
self.addGestureRecognizer(tapGest)
panGest = UIPanGestureRecognizer(target: self, action: #selector(CustomSwitch.panned))
button.addGestureRecognizer(panGest)
}
//MARK:- GestureRecognizers
@objc func tapped() {
switchDirection()
}
@objc func panned(_ panRecognizer: UIPanGestureRecognizer) {
let translation = panRecognizer.translation(in: self).x
switch panRecognizer.state {
case .changed:
if translation >= -13 && translation <= 13 {
if minMaxButtonConstraint + translation <= 13 {
buttonLeadingConstraint.constant = minMaxButtonConstraint + translation
}
}
case .ended:
switchDirection()
default:
print("Default")
}
}
@objc func switchDirection() {
self.layoutIfNeeded()
if isSwitched {
buttonLeadingConstraint.constant = 4
minMaxButtonConstraint = 0
self.backgroundColor = .switchGrey
isSwitched = false
}
else {
buttonLeadingConstraint.constant = 14
minMaxButtonConstraint = 14
self.backgroundColor = .customPurple
isSwitched = true
}
let switchButton = UIViewPropertyAnimator(duration: 0.4, curve: .easeInOut) {
self.layoutIfNeeded()
}
switchButton.startAnimation()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
The class Where I am using this customSwitch as a component is basically a UITabelViewCell class.
class SpaceDetailTableViewCell: UITableViewCell {
var typeLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "Roof Light"
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
return lbl
}()
-----------------------------------------------------------------------
-----How do i get tap and Pan gestures from this switchButton???------
-----------------------------------------------------------------------
var switchBtn: CustomSwitch = {
let swtch = CustomSwitch()
swtch.translatesAutoresizingMaskIntoConstraints = false
return swtch
}()
var onOffLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "Off / On"
lbl.font = UIFont.systemFont(ofSize: 14, weight: .regular)
return lbl
}()
var intensityLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "Intensity"
lbl.font = UIFont.systemFont(ofSize: 14, weight: .regular)
return lbl
}()
var imageOfDevice: UIImageView = {
let v = UIImageView()
v.translatesAutoresizingMaskIntoConstraints = false
v.contentMode = .scaleAspectFill
v.image = #imageLiteral(resourceName: "lightImage")
return v
}()
var intensityContainer: Container = {
let v = Container()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .customPurple
v.layer.cornerRadius = 10
v.clipsToBounds = true //Because cornerRadius wasn't working
return v
}()
var percentageLabel: UILabel = {
let lbl = UILabel()
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.text = "65%"
lbl.font = UIFont.systemFont(ofSize: 16, weight: .medium)
lbl.textColor = .customPurple
return lbl
}()
var separatorLine: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .switchGrey
return v
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
setupCell()
addLinesInIntensityContainer(View: intensityContainer)
let panGest = UIPanGestureRecognizer(target: self, action: #selector(swipeUpDown(_:)))
intensityContainer.addGestureRecognizer(panGest)
}
func setupCell() {
contentView.addSubview(typeLabel)
contentView.addSubview(switchBtn)
contentView.addSubview(onOffLabel)
contentView.addSubview(intensityLabel)
contentView.addSubview(imageOfDevice)
contentView.addSubview(intensityContainer)
contentView.addSubview(percentageLabel)
contentView.addSubview(separatorLine)
NSLayoutConstraint.activate([
typeLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 25),
typeLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25),
//SwitchButton
switchBtn.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40),
switchBtn.topAnchor.constraint(equalTo: typeLabel.topAnchor),
switchBtn.widthAnchor.constraint(equalToConstant: 32),
switchBtn.heightAnchor.constraint(equalToConstant: 20),
//OnOffLabel
onOffLabel.centerXAnchor.constraint(equalTo: switchBtn.centerXAnchor),
onOffLabel.topAnchor.constraint(equalTo: switchBtn.bottomAnchor, constant: 4),
//IntensityLabel
intensityLabel.centerXAnchor.constraint(equalTo: onOffLabel.centerXAnchor),
intensityLabel.topAnchor.constraint(equalTo: onOffLabel.bottomAnchor, constant: 10),
//ImageView
imageOfDevice.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 25),
imageOfDevice.topAnchor.constraint(equalTo: typeLabel.bottomAnchor, constant: 25),
imageOfDevice.widthAnchor.constraint(equalToConstant: 180),
imageOfDevice.heightAnchor.constraint(equalToConstant: 215),
imageOfDevice.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12),
//IntensityContainer
intensityContainer.trailingAnchor.constraint(equalTo: separatorLine.trailingAnchor),
intensityContainer.topAnchor.constraint(equalTo: intensityLabel.bottomAnchor, constant: 10),
intensityContainer.widthAnchor.constraint(equalToConstant: 65),
intensityContainer.heightAnchor.constraint(equalToConstant: 140),
//PercentageLabel
percentageLabel.centerXAnchor.constraint(equalTo: intensityContainer.centerXAnchor),
percentageLabel.topAnchor.constraint(equalTo: intensityContainer.bottomAnchor, constant: 10),
//SeparatorLine
separatorLine.leadingAnchor.constraint(equalTo: imageOfDevice.leadingAnchor),
separatorLine.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -25),
separatorLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -1),
separatorLine.heightAnchor.constraint(equalToConstant: 1)
])
}
@objc func swipeUpDown(_ panRecognizer: UIPanGestureRecognizer) {
let translation = panRecognizer.translation(in: self).y
switch panRecognizer.state {
case .began:
intensityContainer.setNeedsDisplay()
case .changed:
if translation > 0 && translation < 140 {
Translation.translationInContainer = translation
intensityContainer.setNeedsDisplay()
}
case .ended:
Translation.translationEndedInContainer = translation
default:
print("Default")
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
question from:
https://stackoverflow.com/questions/65651421/how-to-handle-gesture-in-another-viewcontroller-swift