让键盘阻止单元格

问题描述:

我的应用程序显示一个表单,并且在某些单元格上有可输入信息的文本框。如果单元格朝向屏幕的底部,单元格将被完全阻塞,这意味着您无法看到您正在回答的问题。我的UITableView嵌入在UIViewController中。让键盘阻止单元格

我已经浏览了许多建议这个问题的答案并实现了一些代码的线程。如果我能得到这个方法的工作,我相信我的代码将工作:

func textFieldDidBeginEditing(_ textField: UITextField) { 
    if (self.tableView.contentOffset.y == 0) 
    { 
     self.tableView.scrollToRow(at: self.tableView.indexPath(for:), at: UITableViewScrollPosition, animated: true) 
    } 
} 

现在我正在努力解决越来越活跃的细胞,以便它可以被输入到self.tableView.indexPath(for:)的问题。

我该怎么做呢?这是移动键盘上方视图的正确方法吗?

+0

可以请你告诉我表单是动态的还是静态的,如果是静态的,那么就有很简单的方法来实现它,而不需要任何代码。 –

+0

我已经使用[IQKeyboardManager](https://github.com/hackiftekhar/IQKeyboardManager)来移动文本框,以防止它们被阻止。到目前为止,它对我来说非常有用。 – NerdsGeeksGurus

+0

使用键盘通知来处理此类问题 –

退房这个问题的答案后由我
iOS Support External Keyboard Without Displaying One

此外,对于的tableView,我使用这样的与键盘显示适当的单元格。

func textFieldDidBeginEditing(_ textField: UITextField) { 
    tableView.isScrollEnabled = false 
    var path: IndexPath? 

    path = theIndexPathOfTheCellWithTheTextField 

    if path != nil { 
     let rect = CGRect(x: 0, y: 0, width: tableView.frame.width, height: tableView.frame.height) 
     tableView.tableFooterView = UIView(frame: rect) 

     UIView.animate(withDuration: 0.6, animations: { 
      [weak self] in 
      self?.tableView.scrollToRow(at: path!, at: .top, animated: false) 
     }, completion: nil) 
    } 
} 

func textFieldDidEndEditing(_ textField: UITextField) { 
    tableView.tableFooterView = UIView() 
    tableView.isScrollEnabled = true 
} 

如果您具有的tableView的tableFooterView一个UI,比这部分代码可能需要改变或基于页脚视图可用大小中删除。

编辑 - 更多信息: 为了做一个indexPath,你有几个选项。您只需硬编码,如果你知道了细胞的位置,像这样:

//This works where neither theRowInt or theSectionInt are negative. 
IndexPath(row: theRowInt, section: theSectionInt) 

//So this would be the first section/first row 
IndexPath(row: 0, section: 0) 

下一个办法是将它基于您通过文本框找到电池:

let textFieldCell = textField.superview.superview.superview as! UITableViewCell 
let indexPath = self.tableView.indexPathForCell(textFieldCell) 

这工作假设你这是正确的监视次数。如果将textField直接放入contentView中,则无论如何,这应该是自iOS 7以来的正确数字。如果它崩溃,不仅仅是改变.superviews的数量直到它工作。

还有其他的方法,但如果你对它们感兴趣,那么自己研究一下。关于这个问题,Here是一个很好的堆栈溢出帖子。

+0

如何获取theIndexPathOfTheCellWithTheTextField?似乎如果我能弄清楚,我可以运行我的上述代码。 –

+0

检查我即将编辑的编辑。 – Sethmr

+0

所以我试过这个解决方案后没有与我的运气和另一个......这一个也没有工作。当我点击一个文本框时,tableview根本不会滚动。多一点信息。我正在使用我创建的自定义tableviewcells。 uitableview放置在我的uiviewcontroller中的2个uiviews之间。我不知道这是否对正确滚动有影响。任何想法如何我可以调试这个? –

在您的应用中使用https://github.com/hackiftekhar/IQKeyboardManager。它会保持文本框和键盘设置自己。

到目前为止,最简单的解决方案是使用UITableViewController而不是带有tableView属性的UIViewController

它自动神奇地为您处理它。我很清楚有些情况下你不能使用UITableViewController,但是如果可能的话,你应该。使用在常规控制器中嵌入UITableViewController的容器视图控制器,即使在更复杂的情况下也可以实现这一点。

在viewWillAppear中你UIKeyboardWillShow和UIKeyboardWillHide注册通知:

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

然后keyboardWillShow你键盘的框架,改变的tableView

func keyboardWillShow(notification: Notification) { 
    guard let keyboardFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return } 
     let convertedFrame = view.convert(keyboardFrame, from: nil) 
     tableView.contentInset.bottom = convertedFrame.height 
} 

然后keyboardWillHide你改变的插图底部插入回到0,并且如果需要的话,将tableView滚动回特定行。这将它滚动回位于tableView顶部的第一行。

func keyboardWillHide(notification: Notification) { 
    tableView.contentInset.bottom = 0 
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true) 
} 

这也是一个很好的方法来做到这一点,因为它让你的textField代理与影响布局的代码保持一致。

我相信我读的地方,你不需要删除自己观察员某些通知,其中包括键盘通知,但为了稳妥起见,你应该把这些在viewWillDisappear或DEINIT视情况

deinit { 
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillShow, object: nil) 
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillHide, object: nil) 

    // If you don't have any other notifications you wan't to keep observing you can remove yourself from all observers by using this one line 
    // NotificationCenter.default.removeObserver(self) 
    } 

使用通知中心。

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

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