UITextField和UITableViewCell自动滚动

时间:2017-03-08 09:28:41

标签: ios swift uitableview scroll

以下是使用UITextFields和高UITableViewCells处理滚动的最佳方法吗?

我有一个UITableView,里面有高大的单元格和UITextFields,从上到下分布。高,我的意思是当键盘弹出时,整个单元格都无法显示。

当依赖于默认行为时,如果选择位于单元格顶部的UITextField,则自动滚动不起作用。这似乎是非常基本的,并始终滚动到底部位置,这导致最顶层的UITextFields(包括所选的一个)被隐藏。

因此,我使用UIKeyboardWillShow / UIKeyboardDidShow通知。

我首先尝试将此行为仅用于顶部的UITextFields,否则依赖于默认行为,但由于某种原因,自动滚动不再可靠,所以我选择了手动滚动。

这是我正在使用的(有点“经典”)代码。 基本上,我只是告诉tableview滚动到哪里,根据所选的UITextField更改UITableViewScrollPosition

var scrollTo: (indexPath: IndexPath, position: UITableViewScrollPosition)?

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    registerForKeyboardNotifications()
}

override func viewWillDisappear(_ animated: Bool) {
    unregisterForKeyboardNotifications()
    super.viewWillDisappear(animated)
}

func registerForKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
}

func unregisterForKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
}

func keyboardWillShow() {
    tableView.isScrollEnabled = scrollTo == nil
}

func keyboardDidShow() {
    guard let scrollTo = scrollTo else { return }
    self.scrollTo = nil
    tableView.scrollToRow(at: scrollTo.indexPath, at: scrollTo.position, animated: true)
    tableView.isScrollEnabled = true
}

/// Textfields are tagged to allow UITextFieldDelegate method identification
/// I renamed each text field according to its location in the cell for sake of clarity
enum CellTextField: Int {
    case topFieldA = 1, topFieldB, middleFieldA, bottomFieldA, bottomFieldB

    static let multiplier = 10

    static func identifiersFrom(cellTag: Int) -> (cellTextField: CellTextField, indexPath: IndexPath)? {
        guard let cellTextField = CellTextField(rawValue: cellTag % CellTextField.multiplier) else {
            return nil
        }
        let indexPath = IndexPath(row: cellTag / CellTextField.multiplier, section: 0)
        return (cellTextField, indexPath)
    }

    func tagFor(row: Int) -> Int {
        return row * CellTextField.multiplier + self.rawValue
    }
}

/// When the textfield is selected, I retrieve the indexPath from the textfield tag
/// (set by tableView(tableView:cellForRowAt indexPath:)) and set the most relevant
//// scrollTo position according to the textfield position in the cell
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    guard let identifiers = CellTextField.identifiersFrom(cellTag: textField.tag) else { return true }
    switch identifiers.cellTextField {
    case .topFieldA, . topFieldB:
        scrollTo = (identifiers.indexPath, .top)
    case . middleFieldA:
        scrollTo = (identifiers.indexPath, .middle)
    case .bottomFieldA, . bottomFieldB:
        scrollTo = (identifiers.indexPath, .bottom)
    }
    return true
}

以上代码运行正常,对于有高细胞的罪行来说,这似乎是一个很大的开销。或者这是处理这个问题的正确方法吗?

1 个答案:

答案 0 :(得分:0)

我将缺少答案:是的,这是处理它的正确方法。