Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Darkened overlay while user is typing

When the user taps on a text field, I wanted to darken the rest of the screen (everything below the text box, above the keyboard) to make it clear what they should be doing. I believe it involved putting a transparent UI view down and adding a gesture recognizer to it, but I'm not quite sure how to do that.

I've got the following code for when the user arrives on the screen. Is this where I would add the new UI View?

override func viewWillAppear(animated: Bool) {
  super.viewWillAppear(animated)
  textField.becomeFirstResponder()
}

Thanks!

like image 804
xavdid Avatar asked Nov 25 '25 13:11

xavdid


1 Answers

I created a subclass of UIView for two reasons:

  • you can add a gesture recogniser to it
  • you can add a delegate to it

Since the last subview added to a view is on top I first add the dark layer and then call bringSubviewToFront(textview) this will put the dark layer between the textview in question and everything else.

I created a protocol with one function. This function get's called by the gesture recogniser and returns the instance of DarkView to the delegate. The delegate (your ViewController) can then remove it from it's superview. This you can do without a delegate function, but you also have to call resignFirstResponder() on the textfield.

Don't forget to set up the delegate of the DarkView in your ViewController.

Just a VC with some textfields.

class FirstViewController: UIViewController, DarkViewDelegate, UITextFieldDelegate {

    var masterView : UIView!

    override func viewDidLoad() {

        super.viewDidLoad()

        masterView = UIView(frame: self.view.frame)
        masterView.backgroundColor = UIColor.whiteColor()

        let textField1 = UITextField(frame: CGRect(x: 50, y: 20, width: 300, height: 20))
        let textField2 = UITextField(frame: CGRect(x: 50, y: 60, width: 300, height: 20))
        let textField3 = UITextField(frame: CGRect(x: 50, y: 100, width: 300, height: 20))
        let textField4 = UITextField(frame: CGRect(x: 50, y: 140, width: 300, height: 20))

        func styleTextField(field : UITextField) {
            field.layer.borderColor = UIColor.blackColor().CGColor
            field.layer.borderWidth = 2
            field.layer.cornerRadius = field.frame.size.height / 2
            field.backgroundColor = UIColor.whiteColor()
            field.delegate = self
            masterView.addSubview(field)
        }

        styleTextField(textField1)
        styleTextField(textField2)
        styleTextField(textField3)
        styleTextField(textField4)

        self.view.addSubview(masterView)
        // Do any additional setup after loading the view, typically from a nib.

    }

    // delegate function of a textfield 
    func textFieldDidBeginEditing(textField: UITextField) {
        focusUserOn(textField) // darken everything else
    }

    // delegate function of DarkView undarken everything
    func tappedDark(view: DarkView) {

        guard let superV = view.superview else {
            return
        }

        if let textField = superV.subviews.last as? UITextField {
            textField.resignFirstResponder() // also stop editing
        }

        view.removeFromSuperview()
    }

    func focusUserOn(textfield: UITextField) {

        guard let superV = textfield.superview else {
            return
        }

        let darkArea = DarkView(frame: superV.bounds)
        darkArea.delegate = self
        superV.addSubview(darkArea)// add DarkView (everything is dark now)

        superV.bringSubviewToFront(textfield) // bring the textview back to the front.
    }

}

simple subclass of UIView with a gesture recogniser

class DarkView : UIView, UIGestureRecognizerDelegate {

    weak var delegate : DarkViewDelegate?

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.4)
        let tap = UITapGestureRecognizer(target: self, action: Selector("tapped"))
        tap.delegate = self
        self.addGestureRecognizer(tap)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    deinit {
        print("deinit dark")
    }

    func tapped() {
        guard let del = self.delegate else {
            return
        }
        del.tappedDark(self)
    }
}

Protocol to pass the DarkView when it is tapped to a VC

protocol DarkViewDelegate : class {

    func tappedDark(view:DarkView)

}

After thought

func textFieldDidEndEditing(textField: UITextField) {
    guard let superV = view.superview else {
        return
    }

    for subview in superV.subviews {

        if subview is DarkView {
            subview.removeFromSuperview()
        }

    }
}
like image 148
R Menke Avatar answered Nov 28 '25 01:11

R Menke