2

New to Swift.

When a user clicks on a text field to begin typing, is there a way to disable all user interaction other than typing into that text field? I want it so that the user is unable to click outside the text field, and should press the return key to dismiss keyboard, where user interaction is enabled again (I have the dismiss keyboard part set up).

I know that the isUserInteractionEnabled function can stop all interaction, but I still want the user to be able to interact with the keyboard.

Thanks

10
  • Should not be automatic, you need to code it like that, disabling programmatically all other functionality. Commented Jan 9, 2017 at 20:49
  • right. that's what im wondering how to do. I know userInteractionEnabled can stop all interaction but i still want the user to be able to interact with the keyboard Commented Jan 9, 2017 at 20:53
  • For Example, for a UI Button, you should do yourButtonName.isEnabled = false Commented Jan 9, 2017 at 21:05
  • right that's for buttons, but i want to disable user interaction except for interacting with the keyboard Commented Jan 9, 2017 at 21:10
  • 1
    @brownmamba since you have not accepted an answer, I believe you are still looking for a answer. I don't have a coded solution but why not mask your entire view with another view when the keyboard comes out? This also allows you to give a color to the mask view (with say opacity of 0.4) that will help users understand why nothing would happen on clicking outside the keyboard area. You can use UIKeyboardWillShowNotification and UIKeyboardWillHideNotification to calculate the size, and show/hide the mask view. Commented Jan 10, 2017 at 0:51

2 Answers 2

1

So, the first idea, which came up to me is disabling every UI element into your view while you're focused on the UITextField instance.

Create a function, which will obtain a UI element as an argument (UITextField for ex). In the function's body start to check every UI element and cyclically disable everyone, which will not equal to the passed argument. You can verify your text field for the type and text additionally.

Here's draft of the function's body:

func disableAll(exceptInput element: UITextField) {
    for item in self.view.subviews {
        if item != element {
            item.isUserInteractionEnabled = false
        } else {
            item.isUserInteractionEnabled = true
        }
    }
}

And perform this method in the text field action, for ex. in the onDidStart.

And, obviously, don't forget about enabling all elements for user interaction. The code is simple:

func enableAll() {
    for item in self.view.subviews {
        item.isUserInteractionEnabled = true
    }
} 

This method you can perform on the onDidEnd IBAction for every UITextField. The last step is necessary if you want to run the normal application behavior.

Sign up to request clarification or add additional context in comments.

1 Comment

This is very close to what i am trying to achieve. I'm working with table view cells and have one textField element to control all the cells. So with your answer the user could press on another cell's textField and interaction would be enabled. Is there a way to just focus on one cell's textField? So they can't even click on other textFields?
0

The behavior you describe is can be accomplished by manipulating the Boolean isEnabled value if UI elements. There are a couple of steps to make this smooth and user friendly.

Just good practice, and not required for this example, but I like to make extension of the MyViewController, to subscribe/unsubscribe to keyboard notifications and so on in it, like so:

import Foundation
import UIKit

extension MyViewController {            

    //MARK: Subscribing/Unsubribing to NotificationCenter.
    func subcribeToKeyboardNotifications(){    
         NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    func unsubscribeToKeyboardNotifications(){
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    //MARK: Screen manipulation methods, to move the UIView up when the bottom text field is editing.
    func keyboardWillShow(_ notification: Notification) {
        if bottomTextField.isEditing {
            view.frame.origin.y =  getKeyboardHeight(notification) * -1
        }
    }

    func keyboardWillHide(_ notification: Notification) {
        if bottomTextField.isEditing {
            view.frame.origin.y = 0
        }
    }

    //MARK: Value returning method to calculate keyboard height.
    private func getKeyboardHeight(_ notification: Notification) -> CGFloat {
        let userInfo = (notification as NSNotification).userInfo!
        let keyboardSize = userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue
        return keyboardSize.cgRectValue.height
    } 
}

Next, in MyViewController, I set the keyboard to resignToFirstResponder() when the return key is tapped, and I make sure to set my UITextFieldDelegates.

import Foundation
import UIKit

class MyViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var someButton: UIButton!
    @IBOutlet weak var topTextField: UITextField!
    @IBOutlet weak var bottomTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        //Set the delegates to self, it this example.
        topTextField.delegate = self
        bottomTextField.delegate = self
        enableUIElements(true)
    }

    //Delegate function to type stuff into the text field.
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        enableUIElements(false)
        var newText = textField.text! as NSString
        newText = newText.replacingCharacters(in: range, with: string) as NSString
        let textSize: CGSize = newText.size(attributes: [NSFontAttributeName: textField.font!])
        return textSize.width < textField.bounds.size.width
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder() //Dismiss the keyboard.
        enableUIElements(true) //enable the UI elements.
        return true
    }

    //Create a function to enable/disable UI elements.
    func enableUIElements(_ enable: Bool){
        someButton.isEnabled = enable
        //TODO: add other elements here.
    }
}

Note that last function!!! Use it to enable/disable other elements while the keyboard is active, as I've shown.

That should get you where you need to go :)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.