我有一个表视图,该表视图使用带有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()
}
}
}
}
答案 0 :(得分:1)
首先,在您的单元格类中 内部 处理您的文本视图操作。然后使用闭包告诉控制器发生了什么事。
因此,当用户点击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
}
}