j166429
j166429

Reputation: 1

UITextView won't scroll when keyboard is displayed

I've implemented some code to scroll the screen when the keyboard is displayed so as to prevent fields from being covered.

This is working fine for Text fields however it's not working for a UITextView field.

Here is the code I've implemented:

  func textFieldDidBeginEditing(textField: UITextField)
{
    //print("textfieldDidBeginEditing")
    activeField = textField
}

func textFieldDidEndEditing(textField: UITextField)
{
    //print("textfieldDidEndEditing")
    activeField = nil
}


func textViewDidBeginEditing(textView: UITextView) {
    print("textViewDidBeginEditing")
    //print(textView)
    activeTextView = textView
    print("1activeTextView:\(activeTextView)")


}

func textViewDidEndEditing(textView: UITextView) {
    print("textViewDidEndEditing")
    //print(textView)
    //print("2activeTextView:\(activeTextView)")
    activeTextView = nil
}



func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    print("yes")
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.scrollEnabled = true
    let info : NSDictionary = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size


    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
   self.scrollView.contentInset = contentInsets
   self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height = keyboardSize!.height



   if (activeField != nil) {
     print("KWSactivfield:\(activeField)")
        if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
        {
            print("!CGRectContainsPoint")
            self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
        }
    }

    if (activeTextView != nil) {
        print("KWSactiveTextView:\(activeTextView)")
        if (!CGRectContainsPoint(aRect, activeTextView!.frame.origin))
        {
             print("true4")
            self.scrollView.scrollRectToVisible(activeTextView!.frame, animated: true)
        }
    }



}


func keyboardWillBeHidden(notification: NSNotification)
{
    //Once keyboard disappears, restore original positions
    let info : NSDictionary = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -2*keyboardSize!.height, 0.0)
    print("insets")
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.scrollEnabled = false

}

I've noticed is that activeTextView is always "nil" once inside the keyboardWasShown function.

Any help would be much appreciated as I can't seem to figure this out.

Thanks!

Upvotes: 0

Views: 168

Answers (1)

Alessandro
Alessandro

Reputation: 2947

i know this is an old post but i had the same problem and i solved it with a little trick. I post here my solution that could be helpful for someone else.

The trick is to assign a value to tag property of all my textviews and then in my keyboardWasShown method read it and, depending on this value, i know which textview was selected. Some codes will help you to understand what i did:

i declared my textviews and an int variable to store the tag value of selected textview:

var myTextViewField: UITextView! = nil
var anotherTextViewField: UITextView! = nil
var activeTextViewTag: Int = 0

in viewDidLoad with all the other properties i've set tag property of my textviews:

myTextViewField.tag = 1
anotherTextViewField.tag = 2

now it's time to read the tag value and i did it in textViewDidBeginEditing method

func textViewDidBeginEditing(_ textView: UITextView) {
    activeTextViewTag = textView.tag
}

In the end, in keyboardWasShown method read the activeTextViewTag value and move the scrollview

func keyboardWasShown(notification: NSNotification){
    print("keyboardWasShown")
    if let userInfo = notification.userInfo {
        if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
            scrollView.contentInset = contentInsets;
            scrollView.scrollIndicatorInsets = contentInsets;
            // If active text field is hidden by keyboard, scroll it so it's visible
            var aRect: CGRect = self.view.frame
            aRect.size.height = aRect.size.height - keyboardSize.height
            var activeField: UITextView! = nil
            if(activeTextViewTag == 1){
                activeField = myTextViewField
            } else {
                activeField = anotherTextViewField
            }

            if(!aRect.contains(activeField.frame.origin)){
                self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
            }

        } else {
            // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
            print("no UIKeyboardFrameBeginUserInfoKey entry in userInfo")
        }
    } else {
        // no userInfo dictionary in notification
        print("no userInfo dictionary in notification")
    }
}

I checked the active field directly in keyboardWasShown but it could be done in a separated method. That's all! This solution perfectly worked for me, i hope this can help someone else!

Upvotes: 1

Related Questions