Hide keyboard by touching background of UITableViewContoller - uitableview

Would like to hide the keyboard while touching on the background of UITableViewContoller. At the moment I have implemented removing keyboard while pressing return but while pressing outside somewhere still not working. My code:
class SecondViewController: UITableViewController, UITextFieldDelegate {
...
// Hide Keyboard while pressing return
func textFieldShouldReturn(textField: UITextField) -> Bool {
tb_Name.resignFirstResponder()
tb_Description.resignFirstResponder()
return true
}
// Hide Keyboard while pressing somewhere on the UI
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}
}
Strange thing is, when I add this code in a "normal" view controller, then it works fine. In an Table View Contoller not.
Thx.

You can probably try to add a gesture on it:
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapGestureRecognizer];
And actually there are so many ways to handle that, it really depends on what you desired behaviors.

Related

How do I detect a touch in navigationController.view?

I was implementing this function.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: self.view) else { return }
for i in 0..<paths.count {
if paths[i].contains(point) { addViews(selectedView: i); break }
}
}
My designers decided they want to make a small part of the views I add to overlay the navigationBar. The problem is that after I add the views to the navigationController.view instead, I am no longer able to detect the touches. I have tried location(in: self.navigationController.view) and that didn't work. Before I go down the rabbit hole of endless different things that might work, does anyone have an easy answer for me?
While navigationController is nominally a ViewController, it's 'view' outlet is usually not used, and probably not put in the responder chain.
My solution was to create a custom view (in the storyboard) as outlet for navigationItem.titleView for the UIViewController.
You can set up the custom view in viewDidLoad() (instead of storyboard)
self.navigationItem.titleView = myCustomView;
In viewDidLoad I set up a gesture like:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleStatusTap:)];
[chatTitleView addGestureRecognizer:singleTap];

Event on tapping out of a UITextView (i.e. UITextView losing focus)

I'd like to perform some processing on my UITextView once the user has finished editing it and tapped somewhere else on the screen. What's the best practice?
I almost managed to get the desired effect with func textViewDidEndEditing(textView: UITextView) however this only runs when the user has tapped 'Enter' key on the keyboard (which people very rarely do - they just commit the changes by tapping on somewhere else on the screen.)
The problem with func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) is that it doesn't care whether the UITextView was edited or not.
I think you can add an UITapGestureRecognizer on the view which hold the textView. In the UITapGestureRecognizer's selector, you can add the logic codes to handle the process. You can check the length of the textView's text to determine the UITextView was edited or not. Here is some sample code:
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tapGestureRecognizer)
}
func handleTap() {
let text = textView.text
textView.resignFirstResponder() // loosing focus
if text.characters.count > 0 {
// textView edited
} else {
// textView not edited
}
}

Hiding the Keyboard at any Touch in Scroll View-Swift Project

How can I hide the keyboard At any touch on the screen, on a view that has a scroll View.
I added this code into viewDidLoad function:
self.NewAccountScrollView.keyboardDismissMode.UIScrollViewKeyboardDismissMode.OnDrag
And I added the UIScrollViewKeyboardDismissMode protocol!
I got errors?
What should I add more to make this works?
Is this the correct way to do that? or there are a better function to do the job?
try to add this, remove UIScrollViewKeyboardDismissMode
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
Add the tap gesture to NewAccountScrollView in ViewDidLoad Method.
let touch = UITapGestureRecognizer(target: self, action: "singleTapGestureCaptured:")
NewAccountScrollView.addGestureRecognizer(touch)
and hide keyboard after receiving tap.
func singleTapGestureCaptured(gesture: UITapGestureRecognizer){
self.view.endEditing(true)
}

Swift - How to dismiss number keyboard after tapping outside of the textfield

How would you dismiss the keyboard from the UITextField when tapping outside of the keyboard. I have tried resignFirstResponder() and it only exits after typing one number. I have also tried textField.inputView = UIView.frame(frame: CGRectZero). I have seen many Obj-C verisons of what I'm asking but I need the Swift equivalent because I have no programming experience in Objective-C
Thank you for your time and patience.
The best way to add a tap gesture recognizer to the view and calling either resignFirstResponder() or self.view.endEditing(true). I prefer endEditing() since resignFirstResponder has to be done for each text field separately unlike endEditing which is done for the view itself.
In viewDidLoad, write the below code:
let tapRecognizer = UITapGestureRecognizer()
tapRecognizer.addTarget(self, action: "didTapView")
self.view.addGestureRecognizer(tapRecognizer)
Now write the didTapView method to dismiss the keyboard:
func didTapView(){
self.view.endEditing(true)
}
Now when you tap outside the keyboard on the main view of the controller, it will call the didTapView method and dismiss the keyboard.
Swift 3.x
The code in viewDidLoad should be:
let tapRecognizer = UITapGestureRecognizer()
tapRecognizer.addTarget(self, action: #selector(ViewController.didTapView))
self.view.addGestureRecognizer(tapRecognizer)
where ViewController should be the name of your view controller.
Thanks
Swift 3 tested and working
// dismiss keyboard on touch outside textfield
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for txt in self.view.subviews {
if txt.isKind(of: UITextField.self) && txt.isFirstResponder {
txt.resignFirstResponder()
}
}
}
Enjoy
Swift 2.3 tested and working
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for txt in self.view.subviews {
if txt.isKindOfClass(UITextField.self) && txt.isFirstResponder() {
txt.resignFirstResponder()
}
}
}
Enjoy
You could also use this method to dismiss the keyboard when pressing 'Return'
func textFieldShouldReturn(textField: UITextField!) -> Bool {
self.view.endEditing(true);
return false;
}
Make sure to set your delegate
If you don't want to define an extra method, there is a slightly simpler way that will also work
let tapRecognizer = UITapGestureRecognizer(target: self, action: "endEditing:")
view.addGestureRecognizer(tapRecognizer)
I found this code on a site and it works great for me!
//FUNCTION TO DISMISS THE KEYBOARD
func initializeHideKeyboard(){
//Declare a Tap Gesture Recognizer which will trigger our dismissMyKeyboard() function
let tap: UITapGestureRecognizer = UITapGestureRecognizer(
target: self,
action: #selector(dismissMyKeyboard))
//Add this tap gesture recognizer to the parent view
view.addGestureRecognizer(tap)
}
#objc func dismissMyKeyboard(){
//endEditing causes the view (or one of its embedded text fields) to resign the first responder status.
//In short- Dismiss the active keyboard.
view.endEditing(true)
}
Then just call this function in a button action or similar:
dismissMyKeyboard()

UIControl endTrackingWithTouch not called

I have a view with a tap gesture recognizer. A subview of this view is an instance of my custom class, which inherits from UIControl. I am having an issue where the UIControl subclass will sometimes allow touch events to pass through to the parent view when it shouldn't.
Within the UIControl subclass, I have overridden these functions (code is in Swift)
override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
return true
}
override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
// The code here moves this UIControl so its center is at the touchpoint
return true
}
override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent)
{
// Something important happens here!
}
This system works just fine if the user touches down within the UIControl, drags the control around in both X and Y directions, and then lifts off the screen. In this case, all three of these functions are called, and the "something important" happens.
However, if the user touches down with the UIControl, drags the control around only in the X direction, and then lifts off the screen, we have a problem. The first two functions are called, but when the touchpoint lifts off the screen, the tap gesture recognizer is called, and endTrackingWithTouch is not called.
How do I make sure that endTrackingWithTouch is always called?
I fixed this in a way that I consider to be a hack, but there's really no alternative, given how UIGestureRecognizer works.
What was happening was that the tap gesture recognizer was canceling the control's tracking and registering a tap gesture. This was because when I was dragging horizontally, I just happened to be dragging short distances, which gets interpreted as a tap gesture.
The tap gesture recognizer must be disabled while the UIControl is tracking:
override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
pointerToSuperview.pauseGestureRecognizer()
return true
}
override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
// The code here moves this UIControl so its center is at the touchpoint
return true
}
override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent)
{
// Something important happens here!
pointerToSuperview.resumeGestureRecognizer()
}
override func cancelTrackingWithEvent(event: UIEvent?)
{
pointerToSuperview.resumeGestureRecognizer()
}
In the superview's class:
pauseGestureRecognizer()
{
tapGestureRecognizer.enabled = false
}
resumeGestureRecognizer()
{
tapGestureRecognizer.enabled = true
}
This works because I'm not dealing with multitouch (it's OK for me not to receive tap touch events while tracking touches with the UIControl).
Ideally, the control shouldn't have to tell the view to pause the gesture recognizer - the gesture recognizer shouldn't be meddling with the control's touches to begin with! However, even setting the gesture recognizer's cancelsTouchesInView to false cannot prevent this.
There's a way to fix this that's nicely self-contained: instantiate your own TapGestureRecognizer and attach it to your custom control, e.g. in Objective-C,
_tapTest = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
_tapTest.numberOfTapsRequired = 1;
[self addGestureRecognizer:_tapTest];
and then implement the tapped action handler to process the tap:
- (void)tapped:(UITapGestureRecognizer *)recognizer {...}
In my case, I handle tapped the same as endTrackingWithTouch:withEvent:; your mileage may vary.
This way, you get the tap before any superview can snatch it, and you don't have to worry about the view hierarchy behind your control.
When a UIControl is moved while tracking touches, it might cancel its tracking. Try overriding cancelTrackingWithEvent and see if this is the case. If you do see the cancel, you're going to have to track your touches in an unmoving view somewhere in the parent hierarchy of this control.
I know this is old, but I run into the same problem, check if one of your superviews has gesture recogniser, and deactivate them when you need to use the UIControl.
I actually ended changed the superview of the UIControl to the main window to avoid this conflicts (Because it was in a popup).

Resources