我有一个带有聊天泡泡的tableView。
如果character count是more than 250,这些气泡就会缩短。
如果用户单击气泡
我想实现什么?
如果已经选择了一个长气泡,但是用户选择了另一个气泡,我希望tableView滚动到新选择的气泡的位置。
我会分享一段关于这件事的视频
如果没有这个滚动,contentOffset仍然是一样的,而且看起来很糟糕。
(在视频中:右边)
视频:
Right:没有上述滚动的 左侧:带滚动的
来了一个问题:
在左边,你可以注意到它是有瑕疵的。
为什么会这样呢?
代码:
func bubbleTappedHandler(sender: UITapGestureRecognizer) {
let touchPoint = sender.location(in: self.tableView)
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
if indexPath == currentSelectedIndexPath {
// Selected bubble is tapped, deselect it
self.selectDeselectBubbles(deselect: indexPath)
} else {
if (currentSelectedIndexPath != nil){
// Deselect old bubble, select new one
self.selectDeselectBubbles(select: indexPath, deselect: currentSelectedIndexPath)
} else {
// Select bubble
self.selectDeselectBubbles(select: indexPath)
}
}
}
}
func selectDeselectBubbles(select: IndexPath? = nil, deselect: IndexPath? = nil){
var deselectCell : WorldMessageCell?
var selectCell : WorldMessageCell?
if let deselect = deselect {
deselectCell = tableView.cellForRow(at: deselect) as? WorldMessageCell
}
if let select = select {
selectCell = tableView.cellForRow(at: select) as? WorldMessageCell
}
// Deselect Main
if let deselect = deselect, let deselectCell = deselectCell {
tableView.deselectRow(at: deselect, animated: false)
currentSelectedIndexPath = nil
// Update text
deselectCell.messageLabel.text = self.dataSource[deselect.row].message.shortened()
}
// Select Main
if let select = select, let selectCell = selectCell {
tableView.selectRow(at: select, animated: true, scrollPosition: .none)
currentSelectedIndexPath = select
// Update text
deselectCell.messageLabel.text = self.dataSource[select.row].message.full()
}
UIView.animate(withDuration: appSettings.defaultAnimationSpeed) {
// Deselect Constraint changes
if let deselect = deselect, let deselectCell = deselectCell {
// Constarint change
deselectCell.nickNameButtonTopConstraint.constant = 0
deselectCell.timeLabel.alpha = 0.0
deselectCell.layoutIfNeeded()
}
// Select Constraint changes
if let select = select, let selectCell = selectCell {
// Constarint change
selectCell.nickNameButtonTopConstraint.constant = 4
selectCell.timeLabel.alpha = 1.0
selectCell.layoutIfNeeded()
}
}
self.tableView.beginUpdates()
self.tableView.endUpdates()
UIView.animate(withDuration: appSettings.defaultAnimationSpeed) {
if let select = select, deselect != nil, self.tableView.cellForRow(at: deselect!) == nil && deselectCell != nil {
// If deselected row is not anymore on screen
// but was before the collapsing,
// then scroll to new selected row
self.tableView.scrollToRow(at: select, at: .top, animated: false)
}
}
}更新1:添加Github项目
链接: https://github.com/krptia/test2
我制作了一个小版本的应用程序,这样你就可以看到并测试我的问题所在。如果有人能帮助解决这个问题,我会非常感激的!
发布于 2019-01-29 09:47:09
首先,让我们来定义我们所说的“不滚动”是什么意思--我们的意思是细胞更少地保持不变。所以我们想要找到一个我们想成为锚细胞的细胞。从更改之前到更改后,从单元格顶部到屏幕顶部的距离是相同的。
var indexPathAnchorPoint: IndexPath?
var offsetAnchorPoint: CGFloat?
func findHighestCellThatStartsInFrame() -> UITableViewCell? {
return self.tableView.visibleCells.filter {
$0.frame.origin.y >= self.tableView.contentOffset.y
}.sorted {
$0.frame.origin.y > $1.frame.origin.y
}.first
}
func setAnchorPoint() {
self.indexPathAnchorPoint = nil;
self.offsetAnchorPoint = nil;
if let cell = self.findHighestCellThatStartsInFrame() {
self.offsetAnchorPoint = cell.frame.origin.y - self.tableView.contentOffset.y
self.indexPathAnchorPoint = self.tableView.indexPath(for: cell)
}
}我们在开始做事之前就把这个叫做。
func bubbleTappedHandler(sender: UITapGestureRecognizer) {
self.setAnchorPoint()
....接下来,我们需要在进行更改之后设置内容偏移量,这样单元格就会移动到应该移动的位置。
func scrollToAnchorPoint() {
if let indexPath = indexPathAnchorPoint, let offset = offsetAnchorPoint {
let rect = self.tableView.rectForRow(at: indexPath)
let contentOffset = rect.origin.y - offset
self.tableView.setContentOffset(CGPoint.init(x: 0, y: contentOffset), animated: false)
}
}接下来,我们在完成更改后调用它。
self.tableView.beginUpdates()
self.tableView.endUpdates()
self.tableView.layoutSubviews()
self.scrollToAnchorPoint()动画可能有点奇怪,因为同时发生了很多事情。我们同时更改内容偏移量和单元格的大小,但是如果您将手指放在顶部可见的第一个单元格旁边,您将看到它在正确的位置结束。
发布于 2019-01-20 23:36:34
尝试在willDisplay上使用UITableViewDelegate api
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if (indexPath == currentSelectedIndexPath) {
// logic to expand your cell
// you don't need to animate it since still not visible
}
}发布于 2019-01-23 07:02:58
用这个替换bubbleTappedHandler的代码,然后运行并检查:
func bubbleTappedHandler(sender: UITapGestureRecognizer) {
let touchPoint = sender.location(in: self.tableView)
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
if indexPath == currentSelectedIndexPath {
currentSelectedIndexPath = nil
tableView.reloadRows(at: [indexPath], with: .automatic)
} else {
if (currentSelectedIndexPath != nil){
if let prevSelectedIndexPath = currentSelectedIndexPath {
currentSelectedIndexPath = indexPath
tableView.reloadRows(at: [prevSelectedIndexPath, indexPath], with: .automatic)
}
} else {
currentSelectedIndexPath = indexPath
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: { [weak self] in
let currentIndexPath = self?.currentSelectedIndexPath ?? indexPath
self?.tableView.scrollToRow(at: currentIndexPath, at: .top, animated: false)
})
}
}https://stackoverflow.com/questions/54278738
复制相似问题