使用UIGestureRecognizer对TableView单元格重新排序

最近,我有幸与一家创业公司的创始人通过咖啡见面,其中一位创始人提到了iPhone上的Weather应用程序。 具体来说,他提到了如何在应用程序中,用户可以重新排序他们对城市的偏好。 外观如下:

尽管这是一个小功能,但我知道这是我可以解决并进一步研究的东西,因为它真的使我对如何编写代码感兴趣。 有几种方法可以在项目中实现这一目标。 我发现了两种不同的方式,我将同时提及两种方式,但仅介绍我的首选方式。

第一种方法是更简便,更快捷的方法。 用户只需要首先运行一个简单的表视图并添加示例数据即可显示。 接下来,在情节提要中或以编程方式添加一个条形按钮项。 实现startEditing方法,然后取消注释canMoveRowAtIndexPath和moveRowAtIndexPath方法。 前者应返回true,而后者应用于对样本数组中的项目重新排序。

第二种方法是我更喜欢的方法,因为您无需实现编辑,并且可以在运行程序后立即重新排列表视图的顺序。 它涉及更多代码,但我认为这是值得的。

这是我采取的步骤。 我很幸运地在线找到了方法论(请参阅此处),并将其转换为Swift 3。

在您的tableview的viewDidLoad中,添加以下代码:

  let longpress = UILongPressGestureRecognizer(目标:自我,行动​​:#selector(TableViewController.longPressGestureRecognized(_ :))) 
  tableView.addGestureRecognizer(longpress) 

接下来创建您的longPressGestureRecognized函数:

  func longPressGestureRecognized(_手势识别器:UIGestureRecognizer){ 
}

在此函数内添加以下代码:

 让longPress = gestureRecognizer为!  UILongPressGestureRecognizer 
让状态= longPress.state
让locationInView = longPress.location(in:tableView)
让indexPath = tableView.indexPathForRow(at:locationInView)
  struct My { 
静态var cellSnapshot:UIView吗? =无
静态var cellIsAnimating:Bool = false
静态var cellNeedToShow:Bool = false
}
结构路径{
静态var initialIndexPath:IndexPath吗? =无
}
 切换状态{ 
案例UIGestureRecognizerState.began:
如果indexPath!= nil {
Path.initialIndexPath = indexPath
让cell = tableView.cellForRow(at:indexPath!)作为UITableViewCell!
My.cellSnapshot = snapshotOfCell(单元格!)
  var center = cell?.center 
My.cellSnapshot!.center =中心!
My.cellSnapshot!.alpha = 0.0
tableView.addSubview(My.cellSnapshot!)
  UIView.animate(withDuration:0.25,animations:{()-> Void in 
中心?.y = locationInView.y
My.cellIsAnimating = true
My.cellSnapshot!.center =中心!
My.cellSnapshot!.transform = CGAffineTransform(scaleX:1.05,y:1.05)
My.cellSnapshot!.alpha = 0.98
cell?.alpha = 0.0
},完成:{(完成)->无效
 如果完成{ 
My.cellIsAnimating = false
 如果My.cellNeedToShow { 
My.cellNeedToShow = false
UIView.animate(withDuration:0.25,animations:{()-> Void in
cell?.alpha = 1
})
}其他{
cell?.isHidden = true
}
}
})
}
 案例UIGestureRecognizerState.changed: 
如果My.cellSnapshot!= nil {
var center = My.cellSnapshot!.center
center.y = locationInView.y
My.cellSnapshot!.center =中心
如果((indexPath!= nil)&&(indexPath!= Path.initialIndexPath)){
itemsArray.insert(itemsArray.remove(at:Path.initialIndexPath!.row),at:indexPath!.row)
tableView.moveRow(at:Path.initialIndexPath !, to:indexPath!)
Path.initialIndexPath = indexPath
}
}
 默认: 
如果Path.initialIndexPath!= nil {
让cell = tableView.cellForRow(at:Path.initialIndexPath!)作为UITableViewCell!
如果My.cellIsAnimating {
My.cellNeedToShow = true
}其他{
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
},完成:{(完成)->无效
 如果完成{ 
Path.initialIndexPath =无
My.cellSnapshot!.removeFromSuperview()
My.cellSnapshot =无
}
})
}
}

接下来在下面添加snapshotOfCell函数

  func snapshotOfCell(_ inputView:UIView)-> UIView { 
  UIGraphicsBeginImageContextWithOptions(inputView.bounds.size,false,0.0) 
inputView.layer.render(in:UIGraphicsGetCurrentContext()!)
让图像= UIGraphicsGetImageFromCurrentImageContext()! 作为UIImage
UIGraphicsEndImageContext()
 让cellSnapshot:UIView = UIImageView(image:图片) 
cellSnapshot.layer.masksToBounds = false
cellSnapshot.layer.cornerRadius = 0.0
cellSnapshot.layer.shadowOffset = CGSize(宽度:-5.0,高度:0.0
cellSnapshot.layer.shadowRadius = 5.0
cellSnapshot.layer.shadowOpacity = 0.4
 返回cellSnapshot 
  } 

最后,请确保实现通常被注释掉的tableview方法。

 覆盖func tableView(_ tableView:UITableView,numberOfRowsInSection部分:Int)-> Int { 
 返回itemsArray.count 
}
 覆盖func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> UITableViewCell { 
  let cell = tableView.dequeueReusableCell(withIdentifier:“ Cell”,for:indexPath)作为UITableViewCell 
  cell.textLabel?.text = itemsArray [indexPath.row] 
cell.textLabel?.textColor? = UIColor.white
 返回单元 
}
 覆盖func tableView(_ tableView:UITableView,didSelectRowAt indexPath:IndexPath){ 
  tableView.deselectRow(at:indexPath,animation:false) 
}

如果您有NBA篮球队的名单,将会是这样。