当新的UITextView被指定为第一响应程序时,如何防止键盘下降



我有一个表视图,它使用带有UITextViews的自定义单元格。每当用户在单元格的textView中编辑文本,然后点击return时,就会在填充表视图单元格的数据列表中插入一个新单元格,并调用tableView.reloadData((,以便新单元格立即显示。用户按下return时正在编辑的单元格的textView.tag+1存储为一个名为cellCreatedWithReturn的变量,如果在重新加载tableView时该变量不为零,则具有该indexPath.row的单元格(因此刚刚创建的新单元格(将成为第一个响应者。

我遇到的问题是,当我按下回车键时,新的单元格会被创建,并被指定为第一响应者,但键盘会弹出,因为它开始隐藏起来,然后又会弹出,而不是停留在原地。苹果的提醒应用程序是一款能展示我想要的功能的应用程序。当您点击回车键时,会创建一个新单元格,并在该新单元格上开始编辑,但键盘会一直保持不动而不会弹出。

我试过的一件事是从我的shouldChangeTextIn函数中注释掉textView.endEditing(true(,看看这是否是键盘降低的原因,但这没有导致任何变化。

以下是我的shouldChangeTextIn和cellForRowAt函数:

var cellCreatedWithReturn: Int?
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if(text == "n") {
textView.endEditing(true)
cellCreatedWithReturn = textView.tag + 1
if song.lyrics.count == textView.tag || song.lyrics[textView.tag].text != "" {
let newLyricLine = LyricLine()
newLyricLine.text = ""
do {
try realm.write {
self.song.lyrics.insert(newLyricLine, at: textView.tag)
print("Successfully inserted new lyric line in Realm")
}
} catch {
print("Error when inserting new lyric line after pressing return")
}
}
tableView.reloadData()
return false
} else {
return true
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "lyricsCell", for: indexPath) as! newNoteTableViewCell

cell.lyricsField.delegate = self

DispatchQueue.main.async {
if let newCellIndexPath = self.cellCreatedWithReturn {
if indexPath.row == newCellIndexPath {
cell.lyricsField.becomeFirstResponder()
}
}
}
}

首先,在单元格类内处理文本视图操作。然后使用闭包告诉控制器发生了什么。

因此,当用户点击Return:时

  • shouldChangeTextIn中截取
  • 使用闭包通知控制器
  • 在控制器中,向数据结构中添加一个元素
  • 使用.performBatchUpdates()在表视图的下一行插入单元格
  • 完成后,将新单元格中的文本视图告知.becomeFirstResponder()

这里有一个非常简单的例子:

// simple cell with a text view
class TextViewCell: UITableViewCell, UITextViewDelegate {

var textView = UITextView()

// closure to tell controller Return was tapped
var returnKeyCallback: (()->())?

// closure to tell controller text was changed (edited)
var changedCallback: ((String)->())?

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
textView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(textView)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([

textView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
textView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
textView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),

// use lessThanOrEqualTo for bottom anchor to prevent auto-layout complaints
textView.bottomAnchor.constraint(lessThanOrEqualTo: g.bottomAnchor, constant: 0.0),

textView.heightAnchor.constraint(equalToConstant: 60.0),
])

textView.delegate = self

// so we can see the text view frame
textView.backgroundColor = .yellow
}

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if(text == "n") {
returnKeyCallback?()
return false
}
return true
}
func textViewDidChange(_ textView: UITextView) {
let t = textView.text ?? ""
changedCallback?(t)
}

}
class AnExampleTableViewController: UITableViewController {

// start with one "row" of string data
var theData: [String] = [ "First row" ]

override func viewDidLoad() {
super.viewDidLoad()
tableView.register(TextViewCell.self, forCellReuseIdentifier: "TextViewCell")
}

override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "TextViewCell", for: indexPath) as! TextViewCell

c.textView.text = theData[indexPath.row]

// handle Return key in text view in cell
c.returnKeyCallback = { [weak self] in
if let self = self {
let newRow = indexPath.row + 1
self.theData.insert("", at: newRow)
let newIndexPath = IndexPath(row: newRow, section: 0)
self.tableView.performBatchUpdates({
self.tableView.insertRows(at: [newIndexPath], with: .automatic)
}, completion: { b in
guard let c = tableView.cellForRow(at: newIndexPath) as? TextViewCell else { return }
c.textView.becomeFirstResponder()
})
}
}

// update data whenever text in cell is changed (edited)
c.changedCallback = { [weak self] str in
if let self = self {
self.theData[indexPath.row] = str
}
}

return c
}

}

相关内容

最新更新