Alan
Alan

Reputation: 9481

Maintain visibility of focused UITextView in a UITableView when showing Keyboard

I am building a form dynamically that has various types of UI elements for each UITableViewCell.

There is one UITableViewCell that contains a UITextView and I want to be able to maintain visibility when showing the keyboard. I have looked at the other similar questions, but have been unable to find a solution.

I wrote the Swift version of what is recommended by: Apple's Managing Keyboard

It does not work for two reasons. 1.) The Keyboard notification is fired before the TextViewWillBeginEditing. 2.) The frame of the UITextView is in relation to the superview which is the UITableViewCell, so the check is wrong.

Here is my current code:

func adjustTableViewForKeyboard(notification: NSNotification) {
        let userInfo = notification.userInfo!

        let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
        let keyboardViewEndFrame = view.convertRect(keyboardScreenEndFrame, fromView: view.window)

        if notification.name == UIKeyboardWillHideNotification {
            self.tableView.contentInset = UIEdgeInsetsZero
        } else {
            self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)

            rect = self.view.frame;
            rect!.size.height -= keyboardViewEndFrame.height

        }
        self.tableView.scrollIndicatorInsets = self.tableView.contentInset

    }


func textViewDidBeginEditing(textView: UITextView) {
        self.activeTextView = textView;

        if(activeTextView != nil){
            // This check does NOT work due to the TextView's superview is the cell.
            if(!CGRectContainsPoint(rect!, (activeTextView?.frame.origin)!)){
                self.tableView.scrollRectToVisible((activeTextView?.frame)!, animated: true)
            }

        }
    }

This works in terms of being able to scroll to all cells, but I also want to make sure the UITextView is not hidden by keyboard.

Upvotes: 1

Views: 1776

Answers (2)

crafterm
crafterm

Reputation: 1881

I had a similar issue with a (albeit static cell) form I was building, I was able to use the scrollToRowAtIndexPath method to update the tableview's row positioning to keep my text view on screen.

func textViewDidBeginEditing(textView: UITextView) {
    if textView == notesTextView {
        tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 3), atScrollPosition: .Top, animated: true)
    }
}

It does require knowledge of the index path section/row and the text view reference in case of multiples, but might be of use?

scrollRectToVisible should also work, but sounds like you have to convert the textview's frame to coordinate system of the scrollview using convertRect:toView or similar first.

Hope this helps - Cheers.

Upvotes: 0

Jeff Kelley
Jeff Kelley

Reputation: 19071

You may be able to use the responder chain to solve this. In your notification handler, try calling isFirstResponder() on your text view; if it returns true, then you can call the table view-scrolling code from there.

Upvotes: 1

Related Questions