Binding a button (UIView) to keyboard that works in multiple textfields (Swift 4.2)





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















Sorry if any similar question(s) has been answered. But, I just can't seem to figure this one out.



I have reached my goal, to bind the "Log In" button to the keyboard, basically pushing it from the bottom of the screen to the top of the keyboard using an extension below.



picture: Initial view without keyboard.



picture: keyboard has been launched.



My UIView extension:



import UIKit

extension UIView{
func bindToKeyboard(){
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}


@objc func keyboardWillChange(_ notification: NSNotification){
let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
let beginningFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let endFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = endFrame.origin.y - beginningFrame.origin.y

UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
self.frame.origin.y += deltaY
}, completion: nil)
}
}


and I called bindToKeyboard() to loginBtn in the viewDidLoad() of my LoginVC like so:



loginBtn.bindToKeyboard()


The problem here is, after the first tap to the textfield (either email or password field), the button disappears. After the keyboard is closed, the button is actually back to its initial position just like in the first picture. Then calling the keyboard again by tapping one of those textfields, the button works properly. But the second and so forth tap, it does not.



The point of my question:




  1. how can I implement the extension to be able to work properly with multiple textfields/textviews?

  2. If that's not possible, how should I approach this problem?


I am sorry if my explanation and or English is unclear.



Thank you so much.










share|improve this question





























    1















    Sorry if any similar question(s) has been answered. But, I just can't seem to figure this one out.



    I have reached my goal, to bind the "Log In" button to the keyboard, basically pushing it from the bottom of the screen to the top of the keyboard using an extension below.



    picture: Initial view without keyboard.



    picture: keyboard has been launched.



    My UIView extension:



    import UIKit

    extension UIView{
    func bindToKeyboard(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }


    @objc func keyboardWillChange(_ notification: NSNotification){
    let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
    let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
    let beginningFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    let endFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let deltaY = endFrame.origin.y - beginningFrame.origin.y

    UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
    self.frame.origin.y += deltaY
    }, completion: nil)
    }
    }


    and I called bindToKeyboard() to loginBtn in the viewDidLoad() of my LoginVC like so:



    loginBtn.bindToKeyboard()


    The problem here is, after the first tap to the textfield (either email or password field), the button disappears. After the keyboard is closed, the button is actually back to its initial position just like in the first picture. Then calling the keyboard again by tapping one of those textfields, the button works properly. But the second and so forth tap, it does not.



    The point of my question:




    1. how can I implement the extension to be able to work properly with multiple textfields/textviews?

    2. If that's not possible, how should I approach this problem?


    I am sorry if my explanation and or English is unclear.



    Thank you so much.










    share|improve this question

























      1












      1








      1








      Sorry if any similar question(s) has been answered. But, I just can't seem to figure this one out.



      I have reached my goal, to bind the "Log In" button to the keyboard, basically pushing it from the bottom of the screen to the top of the keyboard using an extension below.



      picture: Initial view without keyboard.



      picture: keyboard has been launched.



      My UIView extension:



      import UIKit

      extension UIView{
      func bindToKeyboard(){
      NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
      }


      @objc func keyboardWillChange(_ notification: NSNotification){
      let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
      let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
      let beginningFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
      let endFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
      let deltaY = endFrame.origin.y - beginningFrame.origin.y

      UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
      self.frame.origin.y += deltaY
      }, completion: nil)
      }
      }


      and I called bindToKeyboard() to loginBtn in the viewDidLoad() of my LoginVC like so:



      loginBtn.bindToKeyboard()


      The problem here is, after the first tap to the textfield (either email or password field), the button disappears. After the keyboard is closed, the button is actually back to its initial position just like in the first picture. Then calling the keyboard again by tapping one of those textfields, the button works properly. But the second and so forth tap, it does not.



      The point of my question:




      1. how can I implement the extension to be able to work properly with multiple textfields/textviews?

      2. If that's not possible, how should I approach this problem?


      I am sorry if my explanation and or English is unclear.



      Thank you so much.










      share|improve this question














      Sorry if any similar question(s) has been answered. But, I just can't seem to figure this one out.



      I have reached my goal, to bind the "Log In" button to the keyboard, basically pushing it from the bottom of the screen to the top of the keyboard using an extension below.



      picture: Initial view without keyboard.



      picture: keyboard has been launched.



      My UIView extension:



      import UIKit

      extension UIView{
      func bindToKeyboard(){
      NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
      }


      @objc func keyboardWillChange(_ notification: NSNotification){
      let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
      let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
      let beginningFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
      let endFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
      let deltaY = endFrame.origin.y - beginningFrame.origin.y

      UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
      self.frame.origin.y += deltaY
      }, completion: nil)
      }
      }


      and I called bindToKeyboard() to loginBtn in the viewDidLoad() of my LoginVC like so:



      loginBtn.bindToKeyboard()


      The problem here is, after the first tap to the textfield (either email or password field), the button disappears. After the keyboard is closed, the button is actually back to its initial position just like in the first picture. Then calling the keyboard again by tapping one of those textfields, the button works properly. But the second and so forth tap, it does not.



      The point of my question:




      1. how can I implement the extension to be able to work properly with multiple textfields/textviews?

      2. If that's not possible, how should I approach this problem?


      I am sorry if my explanation and or English is unclear.



      Thank you so much.







      ios swift uiview swift4.2






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 16 '18 at 18:47









      Sean SaoirseSean Saoirse

      84




      84
























          2 Answers
          2






          active

          oldest

          votes


















          0














          In this animation, if you use frame to control the position of button, the button is supposed to be free of constrains in vertical direction.



              UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
          self.frame.origin.y += deltaY
          }, completion: nil)


          I use this animation well after removing all the constraints from UIButton. Otherwise, self.frame.origin.y += deltaY should be replaced with constraint constant.



          Good lucky with moving buttons.






          share|improve this answer
























          • This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

            – Mohsin Khubaib Ahmed
            Mar 1 at 10:06



















          0














          I had the exact same problem and initially I tried handling it via the UIKeyboardNotification method but the problem was when the different UITextField was being edited when the Keyboard had changed its state, it won't register for any state change as it was already active. Therefore after much exploring I handled it via creating an accessoryView with a new button that is a duplication of my actual button. So basically, consider you have a UIButton which is sticking at the bottom of the UIViewController and you have 2 UITextField which when switched interchangeably, cannot feel that the UIButton was ever moved elsewhere but remain stuck on the keyboard. This following piece of code explains how to cater this problem:



          @IBOutlet weak var signInBtn: UIButton!
          @IBOutlet weak var passwordTextField: UITextField!
          @IBOutlet weak var emailTextField: UITextField!

          var accessoryViewKeyboard:UIView?
          var btnAccessory:UIButton?


          override func viewDidLoad() {
          super.viewDidLoad()

          passwordTextField.delegate = self
          emailTextField.delegate = self

          accessoryViewKeyboard = UIView(frame: signInBtn.frame)

          //Inputting the "accessoryViewKeyboard" here as the "inputAccessoryView" is of
          //utmost importance to help the "signInBtn" to show up on tap of different "UITextFields"
          emailTextField.inputAccessoryView = accessoryViewKeyboard
          passwordTextField.inputAccessoryView = accessoryViewKeyboard

          setupBtnWithKeyboard()
          }

          func setupBtnWithKeyboard() {
          btnAccessory = UIButton(frame: CGRect(x: signInBtn.frame.origin.x, y: signInBtn.frame.origin.y, width: self.view.frame.size.width, height: signInBtn.frame.size.height))
          accessoryViewKeyboard?.addSubview(btnAccessory!)
          btnAccessory?.translatesAutoresizingMaskIntoConstraints = false
          btnAccessory?.frame = CGRect(x: (accessoryViewKeyboard?.frame.origin.x)!,
          y: (accessoryViewKeyboard?.frame.origin.y)!,
          width: self.view.frame.size.width,
          height: (accessoryViewKeyboard?.frame.size.height)!)

          btnAccessory?.backgroundColor = UIColor(red: 31/255, green: 33/255, blue: 108/255, alpha: 1)
          btnAccessory?.setTitle("Sign In", for: .normal)
          btnAccessory?.titleLabel?.font = .systemFont(ofSize: 22)
          btnAccessory?.titleLabel?.textColor = UIColor.white
          btnAccessory?.titleLabel?.textAlignment = .center
          btnAccessory?.isEnabled = true
          btnAccessory?.addTarget(self, action: #selector(SignIn.signInBtnPressed), for: .touchUpInside)

          NSLayoutConstraint.activate([
          btnAccessory!.leadingAnchor.constraint(equalTo:
          accessoryViewKeyboard!.leadingAnchor, constant: 0),
          btnAccessory!.centerYAnchor.constraint(equalTo:
          accessoryViewKeyboard!.centerYAnchor),
          btnAccessory!.trailingAnchor.constraint(equalTo:
          accessoryViewKeyboard!.trailingAnchor, constant: 0),
          btnAccessory!.heightAnchor.constraint(equalToConstant: signInBtn.frame.size.height),
          ])
          }


          And you're done. This will keep the UIButton always present on the Keyboard. Important thing is no matter how many instances of UITextField you introduce, always input the accessoryViewKeyboard as its inputAccessoryView.






          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53343726%2fbinding-a-button-uiview-to-keyboard-that-works-in-multiple-textfields-swift-4%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            In this animation, if you use frame to control the position of button, the button is supposed to be free of constrains in vertical direction.



                UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
            }, completion: nil)


            I use this animation well after removing all the constraints from UIButton. Otherwise, self.frame.origin.y += deltaY should be replaced with constraint constant.



            Good lucky with moving buttons.






            share|improve this answer
























            • This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

              – Mohsin Khubaib Ahmed
              Mar 1 at 10:06
















            0














            In this animation, if you use frame to control the position of button, the button is supposed to be free of constrains in vertical direction.



                UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
            }, completion: nil)


            I use this animation well after removing all the constraints from UIButton. Otherwise, self.frame.origin.y += deltaY should be replaced with constraint constant.



            Good lucky with moving buttons.






            share|improve this answer
























            • This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

              – Mohsin Khubaib Ahmed
              Mar 1 at 10:06














            0












            0








            0







            In this animation, if you use frame to control the position of button, the button is supposed to be free of constrains in vertical direction.



                UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
            }, completion: nil)


            I use this animation well after removing all the constraints from UIButton. Otherwise, self.frame.origin.y += deltaY should be replaced with constraint constant.



            Good lucky with moving buttons.






            share|improve this answer













            In this animation, if you use frame to control the position of button, the button is supposed to be free of constrains in vertical direction.



                UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
            }, completion: nil)


            I use this animation well after removing all the constraints from UIButton. Otherwise, self.frame.origin.y += deltaY should be replaced with constraint constant.



            Good lucky with moving buttons.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 19 '18 at 1:10









            E.ComsE.Coms

            3,4542416




            3,4542416













            • This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

              – Mohsin Khubaib Ahmed
              Mar 1 at 10:06



















            • This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

              – Mohsin Khubaib Ahmed
              Mar 1 at 10:06

















            This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

            – Mohsin Khubaib Ahmed
            Mar 1 at 10:06





            This answer is invalid. If the button isn't connected to UIViewController's bottom safe area as is the question asked, the button is hanging in the air and can't be moved with the keyboard at all.

            – Mohsin Khubaib Ahmed
            Mar 1 at 10:06













            0














            I had the exact same problem and initially I tried handling it via the UIKeyboardNotification method but the problem was when the different UITextField was being edited when the Keyboard had changed its state, it won't register for any state change as it was already active. Therefore after much exploring I handled it via creating an accessoryView with a new button that is a duplication of my actual button. So basically, consider you have a UIButton which is sticking at the bottom of the UIViewController and you have 2 UITextField which when switched interchangeably, cannot feel that the UIButton was ever moved elsewhere but remain stuck on the keyboard. This following piece of code explains how to cater this problem:



            @IBOutlet weak var signInBtn: UIButton!
            @IBOutlet weak var passwordTextField: UITextField!
            @IBOutlet weak var emailTextField: UITextField!

            var accessoryViewKeyboard:UIView?
            var btnAccessory:UIButton?


            override func viewDidLoad() {
            super.viewDidLoad()

            passwordTextField.delegate = self
            emailTextField.delegate = self

            accessoryViewKeyboard = UIView(frame: signInBtn.frame)

            //Inputting the "accessoryViewKeyboard" here as the "inputAccessoryView" is of
            //utmost importance to help the "signInBtn" to show up on tap of different "UITextFields"
            emailTextField.inputAccessoryView = accessoryViewKeyboard
            passwordTextField.inputAccessoryView = accessoryViewKeyboard

            setupBtnWithKeyboard()
            }

            func setupBtnWithKeyboard() {
            btnAccessory = UIButton(frame: CGRect(x: signInBtn.frame.origin.x, y: signInBtn.frame.origin.y, width: self.view.frame.size.width, height: signInBtn.frame.size.height))
            accessoryViewKeyboard?.addSubview(btnAccessory!)
            btnAccessory?.translatesAutoresizingMaskIntoConstraints = false
            btnAccessory?.frame = CGRect(x: (accessoryViewKeyboard?.frame.origin.x)!,
            y: (accessoryViewKeyboard?.frame.origin.y)!,
            width: self.view.frame.size.width,
            height: (accessoryViewKeyboard?.frame.size.height)!)

            btnAccessory?.backgroundColor = UIColor(red: 31/255, green: 33/255, blue: 108/255, alpha: 1)
            btnAccessory?.setTitle("Sign In", for: .normal)
            btnAccessory?.titleLabel?.font = .systemFont(ofSize: 22)
            btnAccessory?.titleLabel?.textColor = UIColor.white
            btnAccessory?.titleLabel?.textAlignment = .center
            btnAccessory?.isEnabled = true
            btnAccessory?.addTarget(self, action: #selector(SignIn.signInBtnPressed), for: .touchUpInside)

            NSLayoutConstraint.activate([
            btnAccessory!.leadingAnchor.constraint(equalTo:
            accessoryViewKeyboard!.leadingAnchor, constant: 0),
            btnAccessory!.centerYAnchor.constraint(equalTo:
            accessoryViewKeyboard!.centerYAnchor),
            btnAccessory!.trailingAnchor.constraint(equalTo:
            accessoryViewKeyboard!.trailingAnchor, constant: 0),
            btnAccessory!.heightAnchor.constraint(equalToConstant: signInBtn.frame.size.height),
            ])
            }


            And you're done. This will keep the UIButton always present on the Keyboard. Important thing is no matter how many instances of UITextField you introduce, always input the accessoryViewKeyboard as its inputAccessoryView.






            share|improve this answer




























              0














              I had the exact same problem and initially I tried handling it via the UIKeyboardNotification method but the problem was when the different UITextField was being edited when the Keyboard had changed its state, it won't register for any state change as it was already active. Therefore after much exploring I handled it via creating an accessoryView with a new button that is a duplication of my actual button. So basically, consider you have a UIButton which is sticking at the bottom of the UIViewController and you have 2 UITextField which when switched interchangeably, cannot feel that the UIButton was ever moved elsewhere but remain stuck on the keyboard. This following piece of code explains how to cater this problem:



              @IBOutlet weak var signInBtn: UIButton!
              @IBOutlet weak var passwordTextField: UITextField!
              @IBOutlet weak var emailTextField: UITextField!

              var accessoryViewKeyboard:UIView?
              var btnAccessory:UIButton?


              override func viewDidLoad() {
              super.viewDidLoad()

              passwordTextField.delegate = self
              emailTextField.delegate = self

              accessoryViewKeyboard = UIView(frame: signInBtn.frame)

              //Inputting the "accessoryViewKeyboard" here as the "inputAccessoryView" is of
              //utmost importance to help the "signInBtn" to show up on tap of different "UITextFields"
              emailTextField.inputAccessoryView = accessoryViewKeyboard
              passwordTextField.inputAccessoryView = accessoryViewKeyboard

              setupBtnWithKeyboard()
              }

              func setupBtnWithKeyboard() {
              btnAccessory = UIButton(frame: CGRect(x: signInBtn.frame.origin.x, y: signInBtn.frame.origin.y, width: self.view.frame.size.width, height: signInBtn.frame.size.height))
              accessoryViewKeyboard?.addSubview(btnAccessory!)
              btnAccessory?.translatesAutoresizingMaskIntoConstraints = false
              btnAccessory?.frame = CGRect(x: (accessoryViewKeyboard?.frame.origin.x)!,
              y: (accessoryViewKeyboard?.frame.origin.y)!,
              width: self.view.frame.size.width,
              height: (accessoryViewKeyboard?.frame.size.height)!)

              btnAccessory?.backgroundColor = UIColor(red: 31/255, green: 33/255, blue: 108/255, alpha: 1)
              btnAccessory?.setTitle("Sign In", for: .normal)
              btnAccessory?.titleLabel?.font = .systemFont(ofSize: 22)
              btnAccessory?.titleLabel?.textColor = UIColor.white
              btnAccessory?.titleLabel?.textAlignment = .center
              btnAccessory?.isEnabled = true
              btnAccessory?.addTarget(self, action: #selector(SignIn.signInBtnPressed), for: .touchUpInside)

              NSLayoutConstraint.activate([
              btnAccessory!.leadingAnchor.constraint(equalTo:
              accessoryViewKeyboard!.leadingAnchor, constant: 0),
              btnAccessory!.centerYAnchor.constraint(equalTo:
              accessoryViewKeyboard!.centerYAnchor),
              btnAccessory!.trailingAnchor.constraint(equalTo:
              accessoryViewKeyboard!.trailingAnchor, constant: 0),
              btnAccessory!.heightAnchor.constraint(equalToConstant: signInBtn.frame.size.height),
              ])
              }


              And you're done. This will keep the UIButton always present on the Keyboard. Important thing is no matter how many instances of UITextField you introduce, always input the accessoryViewKeyboard as its inputAccessoryView.






              share|improve this answer


























                0












                0








                0







                I had the exact same problem and initially I tried handling it via the UIKeyboardNotification method but the problem was when the different UITextField was being edited when the Keyboard had changed its state, it won't register for any state change as it was already active. Therefore after much exploring I handled it via creating an accessoryView with a new button that is a duplication of my actual button. So basically, consider you have a UIButton which is sticking at the bottom of the UIViewController and you have 2 UITextField which when switched interchangeably, cannot feel that the UIButton was ever moved elsewhere but remain stuck on the keyboard. This following piece of code explains how to cater this problem:



                @IBOutlet weak var signInBtn: UIButton!
                @IBOutlet weak var passwordTextField: UITextField!
                @IBOutlet weak var emailTextField: UITextField!

                var accessoryViewKeyboard:UIView?
                var btnAccessory:UIButton?


                override func viewDidLoad() {
                super.viewDidLoad()

                passwordTextField.delegate = self
                emailTextField.delegate = self

                accessoryViewKeyboard = UIView(frame: signInBtn.frame)

                //Inputting the "accessoryViewKeyboard" here as the "inputAccessoryView" is of
                //utmost importance to help the "signInBtn" to show up on tap of different "UITextFields"
                emailTextField.inputAccessoryView = accessoryViewKeyboard
                passwordTextField.inputAccessoryView = accessoryViewKeyboard

                setupBtnWithKeyboard()
                }

                func setupBtnWithKeyboard() {
                btnAccessory = UIButton(frame: CGRect(x: signInBtn.frame.origin.x, y: signInBtn.frame.origin.y, width: self.view.frame.size.width, height: signInBtn.frame.size.height))
                accessoryViewKeyboard?.addSubview(btnAccessory!)
                btnAccessory?.translatesAutoresizingMaskIntoConstraints = false
                btnAccessory?.frame = CGRect(x: (accessoryViewKeyboard?.frame.origin.x)!,
                y: (accessoryViewKeyboard?.frame.origin.y)!,
                width: self.view.frame.size.width,
                height: (accessoryViewKeyboard?.frame.size.height)!)

                btnAccessory?.backgroundColor = UIColor(red: 31/255, green: 33/255, blue: 108/255, alpha: 1)
                btnAccessory?.setTitle("Sign In", for: .normal)
                btnAccessory?.titleLabel?.font = .systemFont(ofSize: 22)
                btnAccessory?.titleLabel?.textColor = UIColor.white
                btnAccessory?.titleLabel?.textAlignment = .center
                btnAccessory?.isEnabled = true
                btnAccessory?.addTarget(self, action: #selector(SignIn.signInBtnPressed), for: .touchUpInside)

                NSLayoutConstraint.activate([
                btnAccessory!.leadingAnchor.constraint(equalTo:
                accessoryViewKeyboard!.leadingAnchor, constant: 0),
                btnAccessory!.centerYAnchor.constraint(equalTo:
                accessoryViewKeyboard!.centerYAnchor),
                btnAccessory!.trailingAnchor.constraint(equalTo:
                accessoryViewKeyboard!.trailingAnchor, constant: 0),
                btnAccessory!.heightAnchor.constraint(equalToConstant: signInBtn.frame.size.height),
                ])
                }


                And you're done. This will keep the UIButton always present on the Keyboard. Important thing is no matter how many instances of UITextField you introduce, always input the accessoryViewKeyboard as its inputAccessoryView.






                share|improve this answer













                I had the exact same problem and initially I tried handling it via the UIKeyboardNotification method but the problem was when the different UITextField was being edited when the Keyboard had changed its state, it won't register for any state change as it was already active. Therefore after much exploring I handled it via creating an accessoryView with a new button that is a duplication of my actual button. So basically, consider you have a UIButton which is sticking at the bottom of the UIViewController and you have 2 UITextField which when switched interchangeably, cannot feel that the UIButton was ever moved elsewhere but remain stuck on the keyboard. This following piece of code explains how to cater this problem:



                @IBOutlet weak var signInBtn: UIButton!
                @IBOutlet weak var passwordTextField: UITextField!
                @IBOutlet weak var emailTextField: UITextField!

                var accessoryViewKeyboard:UIView?
                var btnAccessory:UIButton?


                override func viewDidLoad() {
                super.viewDidLoad()

                passwordTextField.delegate = self
                emailTextField.delegate = self

                accessoryViewKeyboard = UIView(frame: signInBtn.frame)

                //Inputting the "accessoryViewKeyboard" here as the "inputAccessoryView" is of
                //utmost importance to help the "signInBtn" to show up on tap of different "UITextFields"
                emailTextField.inputAccessoryView = accessoryViewKeyboard
                passwordTextField.inputAccessoryView = accessoryViewKeyboard

                setupBtnWithKeyboard()
                }

                func setupBtnWithKeyboard() {
                btnAccessory = UIButton(frame: CGRect(x: signInBtn.frame.origin.x, y: signInBtn.frame.origin.y, width: self.view.frame.size.width, height: signInBtn.frame.size.height))
                accessoryViewKeyboard?.addSubview(btnAccessory!)
                btnAccessory?.translatesAutoresizingMaskIntoConstraints = false
                btnAccessory?.frame = CGRect(x: (accessoryViewKeyboard?.frame.origin.x)!,
                y: (accessoryViewKeyboard?.frame.origin.y)!,
                width: self.view.frame.size.width,
                height: (accessoryViewKeyboard?.frame.size.height)!)

                btnAccessory?.backgroundColor = UIColor(red: 31/255, green: 33/255, blue: 108/255, alpha: 1)
                btnAccessory?.setTitle("Sign In", for: .normal)
                btnAccessory?.titleLabel?.font = .systemFont(ofSize: 22)
                btnAccessory?.titleLabel?.textColor = UIColor.white
                btnAccessory?.titleLabel?.textAlignment = .center
                btnAccessory?.isEnabled = true
                btnAccessory?.addTarget(self, action: #selector(SignIn.signInBtnPressed), for: .touchUpInside)

                NSLayoutConstraint.activate([
                btnAccessory!.leadingAnchor.constraint(equalTo:
                accessoryViewKeyboard!.leadingAnchor, constant: 0),
                btnAccessory!.centerYAnchor.constraint(equalTo:
                accessoryViewKeyboard!.centerYAnchor),
                btnAccessory!.trailingAnchor.constraint(equalTo:
                accessoryViewKeyboard!.trailingAnchor, constant: 0),
                btnAccessory!.heightAnchor.constraint(equalToConstant: signInBtn.frame.size.height),
                ])
                }


                And you're done. This will keep the UIButton always present on the Keyboard. Important thing is no matter how many instances of UITextField you introduce, always input the accessoryViewKeyboard as its inputAccessoryView.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 2 at 19:02









                Mohsin Khubaib AhmedMohsin Khubaib Ahmed

                7771322




                7771322






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53343726%2fbinding-a-button-uiview-to-keyboard-that-works-in-multiple-textfields-swift-4%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Xamarin.iOS Cant Deploy on Iphone

                    Glorious Revolution

                    Dulmage-Mendelsohn matrix decomposition in Python