防止键盘阻塞单元格

Posted

技术标签:

【中文标题】防止键盘阻塞单元格【英文标题】:Keep keyboard from blocking cell 【发布时间】:2016-11-28 18:09:07 【问题描述】:

我的应用程序显示一个表单,在某些单元格上有可以输入信息的文本字段。如果单元格位于屏幕底部,则单元格将被完全屏蔽,这意味着您无法看到您正在回答的问题是什么。我的 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: )

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

【问题讨论】:

我已使用IQKeyboardManager 移动文本字段,以免它们被阻止。到目前为止,它对我来说效果很好。 你能告诉我表单是动态的还是静态的,如果是静态的,那么无需任何代码就可以很容易地实现它。 使用键盘通知处理此类问题 【参考方案1】:

在您的应用中使用https://github.com/hackiftekhar/IQKeyboardManager。它将保持文本字段和键盘设置本身正常。

【讨论】:

【参考方案2】:

在 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)
   

【讨论】:

【参考方案3】:

使用通知中心。

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)

【讨论】:

【参考方案4】:

查看我对这篇帖子的回答 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)

下一个方法是基于你通过 textField 找到的单元格:

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

假设您的超级视图数量正确,则此方法有效。如果您将 textField 直接放入 contentView,那么这应该是自 iOS 7 以来的正确数字。如果它崩溃,不仅仅是改变 .superviews 的数量直到它工作。

还有其他方法,但如果您对它们感兴趣,请自行研究。 Here 是一个很好的堆栈溢出帖子。

【讨论】:

如何获得IndexPathOfTheCellWithTheTextField?好像我能弄清楚我可以使用上面的代码运行。 所以我在我的和另一个都没有运气之后尝试了这个解决方案......而且这个也不起作用。当我单击文本字段时,tableview 根本不会滚动。只是更多的信息。我正在使用我创建的自定义 tableviewcells。 uitableview 放置在我的 uiviewcontroller 中的 2 个 uiview 之间。我不知道这是否会影响它正确滚动。关于如何调试这个有什么想法吗?【参考方案5】:

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

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

【讨论】:

以上是关于防止键盘阻塞单元格的主要内容,如果未能解决你的问题,请参考以下文章

如何防止表格单元格(不是单个单元格)的列中的换行?

UITableView 重复单元格如何防止呢?迅速

如何防止超过电子表格单元格字符限制的 CSV 数据溢出到相邻单元格?

excelvba锁定单元格图片不被删除

如何防止 UITableViewCellSelectionStyleNone 删除单元格分隔符

防止多个可平移的表格视图单元格被平移