我已经测试了Ilya Puchka的readMoreTextView
吊舱,并在项目内的静态文本上进行了测试。但是我正在尝试使用来自后端api的文本。
问题:单元格不会完全展开以显示所有文本。它将显示下一行高度的大约一半...意味着,如果文本高14像素,则“读取更多”选项将仅显示文本的上半部分。
如果我禁用readmoretext
选项,并使用textView
作为普通textView
,则textview
将显示整个文本,直到滚动为止。 / p>
滚动时,我在一条消息中丢失了大约12行文本。
textView
是否仅适合后端的单个字符串?
所以这告诉我一个tableView.reloadData()
或GCD
问题。但是我迷路了,我不知道该在哪里尝试。测试任何一个选项。
我正在混合两个吊舱AzureBot
和ReadMoreTextView
。字符串/文本来自azure机器人,然后加载到textview中。
我现在意识到我很容易完成这项简单的任务。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let message = self.messages[indexPath.row]
let sending = message.from?.id == BotClient.shared.currentUser.id
switch sending {
case true:
let cell = tableView.dequeueReusableCell(withIdentifier: "UserTableViewCell", for: indexPath) as! UserTableViewCell
cell.transform = tableView.transform
cell.messageLabel.text = message.text
return cell
case false:
let cell = tableView.dequeueReusableCell(withIdentifier: "BotTableCell", for: indexPath) as! BotTableCell
cell.botMessage.text = message.text
cell.botMessage.shouldTrim = !expandedCells.contains(indexPath.row)
cell.botMessage.setNeedsUpdateTrim()
cell.botMessage.layoutIfNeeded()
cell.transform = tableView.transform
return cell
}
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "BotTableCell", for: indexPath) as! BotTableCell
cell.botMessage.onSizeChange = { [unowned tableView, unowned self] r in
let point = tableView.convert(r.bounds.origin, from: r)
guard let indexPath = tableView.indexPathForRow(at: point) else { return }
if r.shouldTrim {
self.expandedCells.remove(indexPath.row)
print("REMOVE CALLED")
} else {
self.expandedCells.insert(indexPath.row)
print("INSERT CALLED")
}
tableView.reloadData()
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "BotTableCell", for: indexPath) as! BotTableCell
cell.botMessage.shouldTrim = !cell.botMessage.shouldTrim
print("SHOULD TRIM CALLED")
cell.backgroundColor = .clear
}
}
这是我的TableViewController
班级:
class TMNEMessageViewController: UITableViewController, UITextViewDelegate {
@IBOutlet weak var navBar: UINavigationItem!
private var observer: AnyObject?
private var needsUpdateViewOnAppearance = true
@IBOutlet var messageBar: MessageBar!
public override var inputAccessoryView: UIView? {return messageBar}
public override var canBecomeFirstResponder: Bool {return true}
private var isVisible: Bool {return isViewLoaded && view.window != nil}
var messages: SortedArray<Activity> { return BotClient.shared.messages }
var expandedCells = Set<Int>()
let readMoreTextAttributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.foregroundColor: UIColor.red,
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16)
]
let readLessTextAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.red,
NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 16)
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 300
tableView.rowHeight = UITableView.automaticDimension
registerCells()
setupObservers()
tableView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: 0) //flip tableview
BotClient.shared.start { r in
if let _ = r.resource {
print(r.printResponseData())
} else if let error = r.error {
print("ERROR: " + error.localizedDescription)
self.displayError(error.localizedDescription)
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if needsUpdateViewOnAppearance {
tableView.reloadData()
needsUpdateViewOnAppearance = false
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
becomeFirstResponder()
}
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if tableView.contentInset == UIEdgeInsets.zero {
updateContentInset(inset: getContentInset())
}
// tableView.reloadData()
}
func registerCells() {
self.tableView.register(UINib(nibName: "BotTableCell", bundle: nil), forCellReuseIdentifier: "BotTableCell")
self.tableView.register(UINib(nibName: "UserTableViewCell", bundle: nil), forCellReuseIdentifier: "UserTableViewCell")
}
fileprivate func setupObservers() {
// Keyboard Notifications
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardDidHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
// BotClient Notifications
NotificationCenter.default.addObserver(self, selector: #selector(handleMessageAdded(notification:)), name: .BotClientDidAddMessageNotification, object: BotClient.shared)
}
@objc
func handleKeyboardNotification(notification: Notification) {
switch notification.name {
case UIResponder.keyboardDidChangeFrameNotification:
if let rect = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
DispatchQueue.main.async {
//print("r \(rect) i \(self.tableView.safeAreaInsets)")
// print(self.tableView.contentInset)
let inset = self.tableView.contentInset
self.updateContentInset(inset: UIEdgeInsets(top: (rect.height + 10) - self.tableView.safeAreaInsets.top, left: inset.left, bottom: inset.bottom, right: inset.right))
}
}
default: return
}
}
func updateContentInset(inset: UIEdgeInsets) {
UIView.animate(withDuration: 0.15, animations: {
self.tableView.contentInset = inset
}, completion: { f in
if self.messages.count > 0 {
self.tableView.scrollToRow(at: IndexPath.init(row: 0, section: 0), at: .top, animated: true)
}
})
}
@objc func handleMessageAdded(notification: Notification) {
DispatchQueue.main.async {
if self.isVisible {
self.tableView.reloadData()
} else {
self.needsUpdateViewOnAppearance = true
}
}
}
func getContentInset() -> UIEdgeInsets {
return UIEdgeInsets(top: max(tableView.safeAreaInsets.top, messageBar.frame.height) - tableView.adjustedContentInset.top, left: 0, bottom: tableView.safeAreaInsets.bottom - tableView.adjustedContentInset.bottom, right: 0)
}
// Err
func displayError(_ message: String?) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}