Make keyboard disappear when clicking outside of Search Bar - SWIFT - ios

I have a UIViewController and I have embedded a Search Bar and a Collection View. When I press on the searchbar, the keyboard appears. I would like to hide this keyboard if the user decides to change his mind by tapping any where on the screen but the search bar. I have tried the following without success:
Adding a Tap Gesture Recognizer
using 'self.mySearchBar.endEditing(true)'
class CollectionViewFolder: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate ,UICollectionViewDelegateFlowLayout, UISearchBarDelegate{
/*** OUTLETS ***/
#IBOutlet weak var mySearchBar: UISearchBar!
// 1. I have tried adding a Tap Gesture Recognizer
// TAP ON SCREEN LISTENER
#IBAction func tapOnScreen(_ sender: UITapGestureRecognizer) {
print("tap tap ...")
self.mySearchBar.resignFirstResponder()
}
// 2. Added the following to the viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.mySearchBar.endEditing(true)
}
}

You can use this extension.
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
Usage. In your viewController:
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
}

Related

How to remove popView if we tap anywhere in the background except tapping in popView in swift

I have created one popView with textfield and button in ViewController. if i click button then popView is appearing, and i am able to enter text in textfield and submit is working, and if i tap anywhere in view also i am able to remove popView, but here i want if i tap on anywhere in popView i don't want to dismiss popView, Please help me in the code.
here is my code:
import UIKit
class PopUPViewController: UIViewController {
#IBOutlet weak var popView: UIView!
#IBOutlet weak var inputField: UITextField!
#IBOutlet weak var textLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
popView.isHidden = true
// Do any additional setup after loading the view.
}
#IBAction func butnAct(_ sender: Any) {
view?.backgroundColor = UIColor(white: 1, alpha: 0.9)
popView.isHidden = false
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(PopUPViewController.dismissView))
view.addGestureRecognizer(tap)
}
#objc func dismissView() {
self.popView.isHidden = true
view?.backgroundColor = .white
}
#IBAction func sendButton(_ sender: Any) {
self.textLabel.text = inputField.text
}
}
In my code if i tap anywhere in the view popView is removing even if i tap on popView also its removing, i don't need that, if i tap on popView then popView need not to be remove.
Please help me in the code
You can override the touchesBegan method which is triggered when a new touch is detected in a view or window. By using this method you can check a specific view is touched or not.
Try like this
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if touch?.view != self.popView {
dismissView()
}
}
func dismissView() {
self.popView.isHidden = true
view?.backgroundColor = .white
}
It's not the way I would have architected this, but to get around the problem you face you need to adapt your dismissView method so that it only dismisses the view if the tap is outside the popView.
To do this modify your selector to include the sender (the UITapGestureRecogniser )as a parameter:
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(PopUPViewController.dismissView(_:)))
and then in your function accept that parameter and test whether the tap is inside your view, and if so don't dismiss the view:
#objc func dismissView(_ sender: UITapGestureRegognizer) {
let tapPoint = sender.location(in: self.popView)
if self.popView.point(inside: tapPoint, with: nil)) == false {
self.popView.isHidden = true
view?.backgroundColor = .white
}
}
Your Popup view is inside the parent view of viewcontroller that's why on tap of popview also your popview is getting hidden.
So to avoid just add a view in background and name it bgView or anything what you want and replace it with view. And it will work fine .
Code:
#IBOutlet weak var bgView: UIView!//Add this new outlet
#IBOutlet weak var popView: UIView!
#IBOutlet weak var inputField: UITextField!
#IBOutlet weak var textLabel: UILabel!
#IBOutlet weak var submitButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
popView.isHidden = true
}
#IBAction func butnAct(_ sender: Any) {
bgView.backgroundColor = UIColor(white: 1, alpha: 0.9)//change view to bgView[![enter image description here][1]][1]
popView.isHidden = false
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissView))
bgView.addGestureRecognizer(tap)//change view to bgView
}
#objc func dismissView() {
self.popView.isHidden = true
bgView.backgroundColor = .white//change view to bgView
}
#IBAction func sendButton(_ sender: Any) {
self.textLabel.text = inputField.text
}

How can the keyboard be closed when opening side menu (SWRevealviewController)?

In my case there is SearchView in the Home Screen and there is also a side menu (which is a SWRevealViewController). Now I want to do that when I click to the UISearchView then the keyboard is opening, without closing that keyboard I open the side menu (SWRevealViewController). This is the process.
Now the problem is that the keyboard remains open after opening the side menu.
What should I do so that after opening the side menu the keyboard is closed automatically?
Now what I tried to do this:
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
Try this code, hope it helps.
class ViewController: UIViewController, SWRevealViewControllerDelegate {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var menuButton:UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if revealViewController() != nil {
menuButton.target = revealViewController()
menuButton.action = "revealToggle:"
self.navigationController!.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
revealViewController().delegate = self
}
}
func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition) {
textField.resignFirstResponder()
}

Swift 3 Gestures + TouchesBegan BUG?

I am using xcode 8.0 & Swift 3.
Here's the overview of my issue:
Scrollview with an imageview named "insidepic" as a subview.
a duplicate of the imageview named "outsidepic" is positioned outside the scrollview.
When "outsidepic" is tapped, touchesBegan is fired.
When "insidepic" is tapped, the tap gesture is fired...but not touchesBegan or touchesEnded are fired.
Here's what I need to solve:
I need for touchesBegan to get fired when the scrollview is tapped. I have added the ".cancelsTouchesInView = false" to the gesture.
Furthermore, the zoom/pan gesturing on the scrollview needs to stay intact. So userinteraction is enabled on both the scrollview & the imageview inside.
This see attached image shows the layout & the viewcontroller swift file.
The yellow area is the scrollview. (with "insidepic" inside)
But, for quick reference, here is my code:
import UIKit
var tap = UITapGestureRecognizer()
class ViewController: UIViewController, UIScrollViewDelegate, UIGestureRecognizerDelegate {
#IBOutlet weak var scroller: UIScrollView!
#IBOutlet weak var insidepic: UIImageView!
#IBOutlet weak var outsidepic: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
scroller.minimumZoomScale = 1
scroller.maximumZoomScale = 6
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
tap.delegate = self
tap.cancelsTouchesInView = false
scroller.addGestureRecognizer(tap)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touches Began")
}
func handleTap(){
print("Tap Gesture Received")
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return insidepic
}
}
MANY THANKS FOR ANY HELP OR INSIGHT YOU CAN OFFER!!

Swift UIScrollView : keyboard doesn't dismiss interactively

I want to dismiss the keyboard interactively, but my code is not working. I don't know why.
When I try the keyboard dismiss mode onDrag it is working fine and there is no need of any more code for that.
Here is my code :
import UIKit
class LoginViewController: UIViewController, UITextFieldDelegate{
#IBOutlet weak var txtUserName: UITextField!
#IBOutlet weak var txtPassword: UITextField!
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBarHidden = false;
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.Interactive
// Do any additional setup after loading the view.
}
#IBAction func LoginTapped(sender: AnyObject)
{
//here my code which is running
}
func textFieldShouldReturn(textField: UITextField!) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.Interactive
}
}
Here are screenshots of the simulator
Please take a look and if possible let me know where the error is.
Use this code. This will end editing when you tap anywhere on the screen.
override func viewDidLoad() {
super.viewDidLoad()
//Looks for single or multiple taps.
var tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "DismissKeyboard")
view.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
func DismissKeyboard(){
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
Hope that helps.
I had the same problem and i finally solved it !
For me the Julian's solution didn't worked so i had to do it as it is :
Set a TapGestureRecognizer in your Storyboard and then an Outlet in your ViewController
#IBOutlet var tapGesture: UITapGestureRecognizer!
Then set an IBAction in your ViewController
#IBAction func DismissKeyboard(sender: UITapGestureRecognizer)
{
self.view.endEditing(true)
}
add these lines to your viewDidLoad method
override func viewDidLoad()
{
super.viewDidLoad()
self.view.addGestureRecognizer(tapGesture)
}
and its should work
Hope that will help !
The below code will work on all the components in the UIView for all the UITextField
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UIView * txt in self.view.subviews){
if ([txt isKindOfClass:[UITextField class]] && [txt isFirstResponder]) {
[txt resignFirstResponder];
}
}
}

Closed:: Creating a UIButton horizontal carousel with swipe and tap gestures

Inside of a VC, I'm trying to figure out how to have a UIButton recognize a horizontal swipe and then tap.
There is an array of text.
var plotList = ["stuff", "to do", "this", "or that"]
default display is plotList[0].
the carousel repeats in an infinite loop doesn't stop at the end of the array.
as user swipes over button only, i don't want the other components of the VC to react to this particular swipe, i want the button to display the plotList string.
when the user taps on the button, i want to shove the result into a switch that will launch the appropriate UIView.
i'd like to avoid doing this UILabel/UIButton combination. See Handling Touch Event in UILabel and hooking it up to an IBAction.
so far i'm here
import UIKit
class carouselVC: UIViewController {
#IBOutlet var carouselView: UIView!
#IBOutlet var labelOutlet: UILabel!
#IBOutlet var buttonOutlet: UIButton!
var plotList = ["stuff", "this", "that"]
let swipeRec = UISwipeGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
var swipeButtonLeft: UISwipeGestureRecognizer =
UISwipeGestureRecognizer(target: self, action: "buttonLeft")
swipeButtonLeft.direction = UISwipeGestureRecognizerDirection.Left
self.buttonOutlet.addGestureRecognizer(swipeButtonLeft)
var swipeButtonRight: UISwipeGestureRecognizer =
UISwipeGestureRecognizer(target: self, action: "buttonRight")
swipeButtonRight.direction = UISwipeGestureRecognizerDirection.Right
self.buttonOutlet.addGestureRecognizer(swipeButtonRight)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func buttonLeft(){
println("buttonLeft")
}
func buttonRight(){
println("buttonRight")
}
#IBAction func buttonAction(sender: UIButton) {
sender.setTitle(plotList[1], forState: .Normal)
}
}
any help?
Use a UIView with a UILabel, instead of button. Add UIView over UILabel and make it clear color. You may make UIlabel look like a button. Add a swipe gesture/tap gesture on it. And do any operation in the action of the gestures.

Resources