Прокрутка содержимого Tableview при отображении клавиатуры

У меня есть табличное представление с текстовым полем и текстовым просмотром. Я реализовал этот код, как это предлагается в этом примере кода яблока. Https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

@IBOutlet var myTableView: UITableView
func keyboardWasShown (notification: NSNotification)
{
    println("keyboard was shown")
    var info = notification.userInfo
    var keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey).CGRectValue().size

    myTableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
    myTableView.scrollIndicatorInsets = myTableView.contentInset
}

func keyboardWillBeHidden (notification: NSNotification)
{
    println("keyboard will be hidden")
    myTableView.contentInset = UIEdgeInsetsZero
    myTableView.scrollIndicatorInsets = UIEdgeInsetsZero
}
  override func viewDidLoad() {

    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)

}

Когда я нажимаю на "текст" вида прокрутки, выходите чуть выше верхней части экрана, но когда я отпускаю клавиатуру, она остается прокруткой вверх. Это точно так же, как свойство insets не может быть изменено после первого раза. Какая моя ошибка?

Ответ 1

Попытайтесь сохранить редактирование пути указателя редактированияIndexPath Получить путь индекса и прокрутить таблицу к этому указательному пути

func keyboardWasShown (notification: NSNotification)
    {
        println("keyboard was shown")
        var info = notification.userInfo
        var keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey).CGRectValue().size

        var contentInsets:UIEdgeInsets

        if UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication().statusBarOrientation) {

            contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
        }
        else {
            contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.width, 0.0);

        }

        myTableView.contentInset = contentInsets

        myTableView.scrollToRowAtIndexPath(editingIndexPath, atScrollPosition: .Top, animated: true)
        myTableView.scrollIndicatorInsets = myTableView.contentInset
    }

Ответ 2

override func viewDidLoad() {
    super.viewDidLoad()

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

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

}

func keyboardWillShow(_ notification:Notification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
    }
}
func keyboardWillHide(_ notification:Notification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    }
}

Ответ 3

Используйте нижеприведенный код, чтобы получить индексный указатель и изменить содержимое UITableview. Смещение на основе высоты UIKeyboard

func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        //self.view.frame.origin.y -= keyboardSize.height
        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)

        var contentInset:UIEdgeInsets = self.tbl.contentInset
        contentInset.bottom = keyboardFrame.size.height
        self.tbl.contentInset = contentInset

        //get indexpath
        let indexpath = NSIndexPath(forRow: 1, inSection: 0)
        self.tbl.scrollToRowAtIndexPath(indexpath, atScrollPosition: UITableViewScrollPosition.Top, animated: true)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        self.tbl.contentInset = contentInset
    }
}

Ответ 4

Используйте это удивительное расширение (обновлено для Swift 4.2),

extension UIViewController {

    func registerForKeyboardWillShowNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil) {
        _ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil, using: { notification -> Void in
            let userInfo = notification.userInfo!
            let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
            let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top, left: scrollView.contentInset.left, bottom: keyboardSize.height, right: scrollView.contentInset.right)

            scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
            block?(keyboardSize)
        })
    }

    func registerForKeyboardWillHideNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil) {
        _ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil, using: { notification -> Void in
            let userInfo = notification.userInfo!
            let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
            let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top, left: scrollView.contentInset.left, bottom: 0, right: scrollView.contentInset.right)

            scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
            block?(keyboardSize)
        })
    }
}

extension UIScrollView {

    func setContentInsetAndScrollIndicatorInsets(_ edgeInsets: UIEdgeInsets) {
        self.contentInset = edgeInsets
        self.scrollIndicatorInsets = edgeInsets
    }
}

и используйте, как указано ниже, из соответствующего ViewController,

@IBOutlet weak var tableview: UITableView!

override func viewDidLoad() {
        super.viewDidLoad()
        registerForKeyboardWillShowNotification(tableview)
        registerForKeyboardWillHideNotification(tableview)

        /* use the above functions with
           block, in case you want the trigger just after the keyboard
           hide or show which will return you the keyboard size also.
         */

        registerForKeyboardWillShowNotification(tableView) { (keyboardSize) in
            print("size 1 - \(keyboardSize!)")
        }
        registerForKeyboardWillHideNotification(tableView) { (keyboardSize) in
            print("size 2 - \(keyboardSize!)")
        }

    }

Ответ 5

** не прокручивается вверх по клавиатуре. **

    override func viewDidLoad() {
    super.viewDidLoad()

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

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

func keyboardWillShow(_ notification:Notification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
    }
}

func keyboardWillHide(_ notification:Notification) 
{
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    }
}

Ответ 6

Вы также можете использовать textfield/textViewDidBeginEditing. Я использовал это для чата tableView.

func textViewDidBeginEditing(_ textView: UITextView) {

    DispatchQueue.main.async {
       if self.chatMessages.count >= 1 {
       let section = self.chatMessages.count - 1
       let row = self.chatMessages[section].count - 1
       let indexPath = IndexPath(row: row, section: section )
       self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
       }
    }
}

Ответ 7

    func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()) != nil {
        //self.view.frame.origin.y -= keyboardSize.height
        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
        keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil)

        var contentInset:UIEdgeInsets = self.tbl.contentInset
        contentInset.bottom = keyboardFrame.size.height
        self.tbl.contentInset = contentInset

        //get indexpath
        let indexpath = NSIndexPath(forRow: 1, inSection: 0)
        self.tbl.scrollToRowAtIndexPath(indexpath, atScrollPosition: UITableViewScrollPosition.Top, animated: true)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()) != nil {
        let contentInset:UIEdgeInsets = UIEdgeInsetsZero
        self.tbl.contentInset = contentInset
    }
}

Ответ 8

У меня была небольшая идея об этом, и я написал расширение на Swift. Не стесняйтесь вносить свой вклад и использовать его в своих проектах:

https://github.com/joluc/AutoAdjust

import Foundation
import UIKit

extension UITableView {
    // I am working on a way to deinit the observers when the tableview also is deiniting.
    // If you have ideas, feel free to help out!
    func setupAutoAdjust()
    {
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardshown), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardhide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    @objc func keyboardshown(_ notification:Notification)
    {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            self.fitContentInset(inset: UIEdgeInsetsMake(0, 0, keyboardSize.height, 0))
        }
    }
    @objc func keyboardhide(_ notification:Notification)
    {
        if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
            self.fitContentInset(inset: .zero)
        }

    }
    func fitContentInset(inset:UIEdgeInsets!)
    {
        self.contentInset = inset
        self.scrollIndicatorInsets = inset
    }
}

Ответ 9

Для Swift 4.2

В viewDidLoad() вашего UIViewController:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)

И реализация селекторов:

@objc private func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
    }
}

@objc private func keyboardWillHide(notification: NSNotification) {
    tableView.contentInset = .zero
}