使用新的 iOS 11 API 重新排序 tableview 时动画不正确
Posted
技术标签:
【中文标题】使用新的 iOS 11 API 重新排序 tableview 时动画不正确【英文标题】:Incorrect animation when reordering tableview with new iOS 11 APIs 【发布时间】:2017-10-06 12:25:26 【问题描述】:我正在使用 ios 11 上的新拖放 API 对同一应用内的 tableview 中的单元格重新排序。
这是我对UITableViewDragDelegate
和UITableViewDropDelegate
的实现:
extension TasksViewController: UITableViewDragDelegate
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]
let string = tasks[indexPath.row]
guard let data = string.data(using: .utf8) else return []
let itemProvider = NSItemProvider(item: data as NSData, typeIdentifier: kUTTypePlainText as String)
let item = UIDragItem(itemProvider: itemProvider)
item.localObject = string
return [item]
extension TasksViewController: UITableViewDropDelegate
func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool
return true
func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal
if session.localDragSession != nil // Drag originated from the same app.
return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
return UITableViewDropProposal(operation: .cancel, intent: .unspecified)
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator)
guard let destinationIndexPath = coordinator.destinationIndexPath,
let dragItem = coordinator.items.first?.dragItem,
let task = dragItem.localObject as? String,
let sourceIndexPath = coordinator.items.first?.sourceIndexPath else
return
tableView.performBatchUpdates(
self.tasks.remove(at: sourceIndexPath.row)
self.tasks.insert(task, at: destinationIndexPath.row)
tableView.deleteRows(at: [sourceIndexPath], with: .none)
tableView.insertRows(at: [destinationIndexPath], with: .none)
)
coordinator.drop(dragItem, toRowAt: destinationIndexPath)
这工作正常,但有一个奇怪的故障。当最后一个单元格被拖动时,一旦它被放下,它就会在表格视图的底部出现一瞬间然后消失。
我在这里错过了什么?
【问题讨论】:
只需将插入和删除动画更改为自动而不是无!就是这样! 【参考方案1】:只需将表格删除动画更改为 .automatic,如下所示:
tableView.deleteRows(at: [sourceIndexPath], with: .automatic)
之后就不会有那个奇怪的动画了。
【讨论】:
我虽然已经尝试过,但显然我没有。现在可以使用了,谢谢!【参考方案2】:首先为swift 4添加pressGesture这个例子
let longpress = UILongPressGestureRecognizer(target: self, action: #selector(longPressGestureRecognized(gestureRecognizer:)))
tableView.addGestureRecognizer(longpress)
功能:
@objc func longPressGestureRecognized(gestureRecognizer: UIGestureRecognizer)
let longPress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longPress.state
let locationInView = longPress.location(in: tableView)
let indexPath = tableView.indexPathForRow(at: locationInView)
struct My
static var cellSnapshot : UIView? = nil
static var cellIsAnimating : Bool = false
static var cellNeedToShow : Bool = false
switch state
case UIGestureRecognizerState.began:
if indexPath != nil
self.Move = indexPath
var cell:UITableViewCell? = UITableViewCell()
cell = tableView.cellForRow(at: indexPath!)
My.cellSnapshot = snapshotOfCell(inputView: cell!)
var center = cell?.center
My.cellSnapshot!.center = center!
My.cellSnapshot!.alpha = 0.0
tableView.addSubview(My.cellSnapshot!)
UIView.animate(withDuration: 0.25, animations: () -> Void in
center?.y = locationInView.y
My.cellIsAnimating = true
My.cellSnapshot!.center = center!
My.cellSnapshot!.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
My.cellSnapshot!.alpha = 0.98
cell?.alpha = 0.0
, completion: (finished) -> Void in
if finished
My.cellIsAnimating = false
if My.cellNeedToShow
My.cellNeedToShow = false
UIView.animate(withDuration: 0.25, animations: () -> Void in
cell?.alpha = 1
)
else
cell?.isHidden = true
)
break;
case UIGestureRecognizerState.changed:
if My.cellSnapshot != nil
var center = My.cellSnapshot!.center
center.y = locationInView.y
My.cellSnapshot!.center = center
if ((indexPath != nil) && (indexPath != Move)) && Move != nil
self.list.insert(self.list.remove(at: Move!.row), at: indexPath!.row) //this line change row index
tableView.moveRow(at: Move!, to: indexPath!)
Move = indexPath
break;
default:
if Move != nil
let cell = tableView.cellForRow(at: Move!)
if My.cellIsAnimating
My.cellNeedToShow = true
else
cell?.isHidden = false
cell?.alpha = 0.0
UIView.animate(withDuration: 0.25, animations: () -> Void in
My.cellSnapshot!.center = (cell?.center)!
My.cellSnapshot!.transform = CGAffineTransform.identity
My.cellSnapshot!.alpha = 0.0
cell?.alpha = 1.0
, completion: (finished) -> Void in
if finished
self.Move = nil
My.cellSnapshot!.removeFromSuperview()
My.cellSnapshot = nil
)
break;
这是单元格视图快照
func snapshotOfCell(inputView: UIView) -> UIView
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
inputView.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let cellSnapshot : UIView = UIImageView(image: image)
cellSnapshot.layer.masksToBounds = false
cellSnapshot.layer.cornerRadius = 0.0
cellSnapshot.layer.shadowOffset = CGSize(width: -5.0,height: 0.0)
cellSnapshot.layer.shadowRadius = 5.0
cellSnapshot.layer.shadowOpacity = 0.4
return cellSnapshot
我希望它会工作:)
【讨论】:
无需长按手势!这是完全不同的事情。 OP 要求其他的东西!以上是关于使用新的 iOS 11 API 重新排序 tableview 时动画不正确的主要内容,如果未能解决你的问题,请参考以下文章
插入后的NSMutableDictionary重新排序元素[重复]