Sorry if this was already asked/answered.
I'm trying to create a CustomButton (UIView) that detects touch down and up (to customize changes in background color, text color, etc).
I've tried touchesBegan
but it reacts too slow.
I've tried UILongPressGestureRecognizer
but it doesn't fall back to dragging a UIScrollView
below. I mean: when dragging over the button it doesn't drag the scroll view.
Here's my solution so far, using UILongPressGestureRecognizer
, with ideas taken from here.
Please, can you think of a better solution than mine? Thanks!
/** View that can be pressed like a button */
import UIKit
class ButtonView : UIView, UIGestureRecognizerDelegate {
static let NoChange = { (btn:ButtonView) in }
var enabled = true
/* Called when the view goes to normal state (set desired appearance) */
var onNormal = NoChange
/* Called when the view goes to pressed state (set desired appearance) */
var onPressed = NoChange
/* Called when the view is released (perform desired action) */
var action = {}
override init(frame: CGRect)
{
super.init(frame: frame)
let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(touched))
recognizer.delegate = self
recognizer.minimumPressDuration = 0.0
addGestureRecognizer(recognizer)
userInteractionEnabled = true
}
override func layoutSubviews() {
super.layoutSubviews()
onNormal(self)
}
func touched(sender: UILongPressGestureRecognizer)
{
guard enabled else { return }
print("Current state: \(sender.state.rawValue)")
if sender.state == .Began {
onPressed(self)
} else if sender.state == .Ended {
onNormal(self)
action()
} else if sender.state == .Changed {
onNormal(self)
// This cancels recognizer when dragging
// TODO: but doesn't drag scroll view
sender.enabled = false
sender.enabled = true
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Usage:
let button = ButtonView()
// add some views to the ButtonView, e.g. add a label
button.onNormal = { $0.backgroundColor = normalColor }
button.onPressed = { $0.backgroundColor = pressedColor }
button.action = { doSomethingWhenButtonIsClicked() }