Mavey Ma
Mavey Ma

Reputation: 11

How to darken/tint background when user clicks UITextView and keyboard appears?

Currently, I am able to make my keyboard appear/hide when I click inside/outside my UITextView. I'd like to make this nicer by tinting the background darker when keyboard appears, and then have the background return to normal when keyboard goes away.

I was told this behavior might be called "Focus" or "Modal Shadow Overlay" but have been unable to find a tutorial or images that match my goal. Here is a screenshot that shows exactly what I want to accomplish: when writing a caption for a new Instagram post, the background tints darker.

  1. How do I implement this behavior in Swift?
  2. What's this behavior called in iOS programming?

Thank you. [:

Upvotes: 1

Views: 1054

Answers (1)

Agent Smith
Agent Smith

Reputation: 2933

First of all to answer your two questions :

  1. There are many ways to implement the overlay.

    • You can add a UIView as a subview, giving it constraints as vertical spacing from textView and aligning the bottom of the self.view and change its alpha when keyboard is presented/dismissed.
    • You can add a MaskView to self.view of a viewcontroller. The problem would be that when a mask is applied it turns all the other area black(Of course you can change color) and only the part that you set in the mask frame will be the color(black with 0.5 alpha) that you suggested.
  2. You can call it adding an overlay(there isn't something else other than adding a mask from Apple's documentation that I've come across)

Now coming to the approach I've been using for a long time.

I add a UIView called overlay variable to my ViewController, Currently setting its frame to CGRect.zero

var overlay: UIView = UIView(frame: CGRect.zero)

After that, I add the Notification Observers for keyboardWillShow and keyboardWillHide in viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

And add the corresponding selectors to handle the Notifications

@objc func keyboardWillShow(notification: NSNotification)
@objc func keyboardWillHide(notification: NSNotification)

In keyboardWillShow, I get the keyboard frame to get the keyboard height

After that, I calculate the height of the overlay by getting the height of the screen and subtracting the navigation bar height, height of the textView and any margin added to the top of textView

Then I initialize my overlay variable by giving it the Y Position of from just below the textView. Initially, I set it's color to be UIColor.clear Add it as a subView to self.view and then changing it's color to black with 0.5 alpha with a 0.5 duration animation.

@objc func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {


        let overlayHeight = UIScreen.main.bounds.height - heightOfNavigationBar - keyboardSize.height - textView.frame.size.height - topConstraintofTextView(if any)

        let overlayFrame = CGRect(x: 0, y: textView.frame.size.height + textView.frame.origin.y, width: UIScreen.main.bounds.width, height: overlayHeight)

        self.overlay = UIView(frame: overlayFrame)
        self.overlay.backgroundColor = .clear
        self.view.addSubview(overlay)
        UIView.animate(withDuration: 0.5, animations: {
            self.overlay.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        })

    }

}

After that, In keyboardWillHide, I change the alpha of overlay to be 0 with a little animation and as soon as it ends I remove the Overlay from superView.

@objc func keyboardWillHide(notification: NSNotification) {

        UIView.animate(withDuration: 0.5, animations: {
            self.overlay.backgroundColor = UIColor.black.withAlphaComponent(0)
        }, completion: { (completed) in
            self.overlay.removeFromSuperview()
        })
        self.overlay.removeFromSuperview()
}

And I do self.view.endEditing(true) in touchesBegan of viewController to dismiss the keyboard but that's upto you how you want to dismiss it.

Here's how it looks

1

Hope it helps!

Upvotes: 3

Related Questions