I cannot seem to figure out how to capture the tap that a user does when they tap outside of a keyboard. The main issue is I have a send button that is not part of the keyboard and I want if they tap it, while the keyboard is open for the send to occur. Currently the user taps the send button which dismisses the keyboard then if they tap the send button again it will send the text.
Just add a tapGesture to your view:
let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped(_:)))
self.view.addGestureRecognizer(tap)
Which will call self.view.endEditing(true) and dismiss the keyboard.
func viewTapped(_ gesture: UITapGestureRecognizer){
self.view.endEditing(true)
}
This does not require any gesture recognizer, and will capture any contact with the screen, dismissing the keyboard.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
view.endEditing(true)
}
Related
If I have a button and starts a touch outside of the buttons bounds and then drag my finger across the screen until I hit the bounds of the button which then will trigger an event. Say change the background color of the button for example (which I know how to). How do I trigger something from that type of touch movement?
I also set my buttons programmatically.
Thanks in advance!
To trigger an action attached to a button when a finger is moving over the button you can use a method touchesMoved(_:with:) of UIViewController.
Firstly, add an action to the button for touchUpInside and touchDragInside inside InterfaceBuilder or in code.
Secondly, override touchesMoved(_:with:) method and call a super. If the super is not called the button UIKit will not trigger any actions on the button. Next, get a touch location inside the view and trigger a touchDragInside action on the button.
#IBOutlet weak var button: UIButton!
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
if let t = touches.first,
button.frame.contains(t.location(in: view)) {
button.sendActions(for: .touchDragInside)
} else {
print("false")
}
}
#IBAction
func didTapButton() {
print("true: touch inside the frame of a button")
}
#IBAction
func didDragInsideButton() {
print("true: touch drag inside the frame of a button")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
button.addTarget(self, action: #selector(didDragInsideButton), for: .touchDragInside)
}
I have a custom pop up which I have made using a UIViewController (presentation: 'over current context') - please see below. What I would like to do is dismiss the UIViewController once the user touches the top - dark half- of the screen, which does not contain the menu options. What event can i trigger to get this to work?
You can add a tap gesture to the darkView and inside it do
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
mydarkView.addGestureRecognizer(tapGesture)
//
// 3. this method is called when a tap is recognized
#objc func handleTap(_ sender: UITapGestureRecognizer) {
self.dismiss(animated:true,completion:true)
}
OR use
override func touchesBegan(_ touches: Set<UITouch>,
with event: UIEvent?)
hi Im new to programming I was try to recognize the user touch on the screen and close all textfield but when I add a scrollview I won't be able to do that I read a lot in stack overflow like : tap recognizer but I could not do that anymore after adding the textfield I got confused
tell me how can I do it please?
thanks
for dismiss the keyboard is the subview of UIView, then use
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
for dismiss the keyboard is the subview of UIScrollview, then use in here scroll view observes the userInteraction so "By setting userInteractionEnabled to NO for your scroll view".
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.yourSCrollviewName.endEditing(true)
}
for resign the keyboard in various types, the some other type has already answered in SO
update
for hide the keyboard the create the TapGesture for your scrollview
self.ScrollView.isUserInteractionEnabled = true
// ScrollView.keyboardDismissMode = .onDrag
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
tap.numberOfTapsRequired = 1
self.ScrollView.addGestureRecognizer(tap)
and call the action as
func doubleTapped() {
// do something cool here
self.ScrollView.endEditing(true)
}
You have to add tap gesture on ScrollView
Add below code in action of gesture:
self.yourSCrollviewName.endEditing(true)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(keyBoardHideOnTap))
tapGesture.numberOfTapsRequired = 1
self.ScrollView.addGestureRecognizer(tapGesture)
func keyBoardHideOnTap() {
// do something cool here
self.ScrollView.endEditing(true)
}
I have used touchesBegan to provide functionality for my UIButtons and have used a tapped gesture to provide functionality for my main player SKSpriteNode making it jump when triggered.
//Code regarding the UIButton touch
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//touches began is only used for GUI buttons -> not to affect player
for touch: AnyObject in touches {
//We get location of the touch
let locationOfTouch = touch.location(in: self)
if muteButton.contains(locationOfTouch) { //mute the game
timer.invalidate()
audioPlayer.volume = 0
}
//Code regarding the tap
let tap = UITapGestureRecognizer(target: self, action: #selector(GameScene.tapped(gesture:)))
tap.cancelsTouchesInView = false
self.view!.addGestureRecognizer(tap)
......
func tapped(gesture: UIGestureRecognizer) { //used to make the player jump
player.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 60))
player.physicsBody!.affectedByGravity = true */
}
My problem is that when I press on the restartButton the tap gesture is also activated later when the touch ends. Is there anything I can do?
The main issue is that the two separate systems for detecting touches (using gesture recognizers and using the touchesBegan/Moved/Ended methods) are in conflict.
One solution is to enable and disable the gesture recognizer if the touch is inside one of the buttons.
In the touchesBegan method, if the touch is inside a button, disable the tap gesture recognizer:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch: AnyObject in touches {
let locationOfTouch = touch.location(in: self)
if muteButton.contains(locationOfTouch) {
// mute action
tap.isEnabled = false
}
}
}
Then in touchesEnded and touchesCancelled, re-enable the gesture recognizer:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
tap.isEnabled = true
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
tap.isEnabled = true
}
This way, if the touch is inside a button, the tap gesture recognizer will not fire. Whenever any touch is complete, we always re-enable the gesture recognizer in case the next touch is meant to make the player jump.
I have tested this out in an empty project, and it works.
Hopefully that helps! Good luck with your game.
I have multiple textFields in different viewControllers where keyboard is popped up.
I know how to dismiss keyboard when user clicks on a different part of the screen but I don't want to go and hard code it into every corner of my app.
So is there anyway to enforce keyboard getting keyboard dismissed everywhere on the app when the user clicks anywhere on the screen other than keyboard?
I was thinking of extending the UIViewController, but I also have some textFields inside a view that I add as a subview. Perhaps there could be someway that I extend TextField class itself?
I suggest to create a base UIViewController and let each of your ViewControllers inherit it; override touchesBegan method in it:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
view.endEditing(true)
}
OR you can override viewDidLoad -in the base ViewController- and add a UITapGestureRecognizer to the view, as follows:
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(Base.endEditing))
view.addGestureRecognizer(tapGesture)
}
func endEditing() {
view.endEditing(true)
}
You can also use an extension of a view controller, if you want the keyboard dismissal to apply to all of them:
extension UIViewController {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}