如何解决当将新的UITextView分配为第一响应者时,如何防止键盘下降
我有一个表视图,该表视图使用带有UITextViews的自定义单元格。每当用户在单元格的textView中编辑文本然后点击回车时,都会将新的单元格插入到填充表格视图单元格的数据列表中,并调用tableView.reloadData()以便立即显示新单元格。用户按下回车键时正在编辑的单元格的textView.tag + 1存储为名为cellCreatedWithReturn的变量,如果重新加载tableView时该变量不为nil,则使用该indexPath.row的单元格(因此,新单元格刚刚创建的)成为第一响应者。
我遇到的问题是,当我按下回车键时,会创建新的单元格并将其分配为第一响应者,但是键盘会闪闪发光,因为它开始藏起来然后又向上射击,而不是仅仅保持原状。可以证明我正在寻找的功能的应用程序将是Apple的Reminders应用程序。当您按回车键时,将创建一个新单元格,并在该新单元格上开始编辑,但是键盘会一直保持启动状态,而不会出现闪烁现象。
我尝试做的一件事是从我的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,textView.trailingAnchor.constraint(equalTo: g.trailingAnchor,// use lessThanOrEqualTo for bottom anchor to prevent auto-layout complaints
textView.bottomAnchor.constraint(lessThanOrEqualTo: g.bottomAnchor,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
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。