如何将静态单元格快速拖动到 tableView 中?
Posted
技术标签:
【中文标题】如何将静态单元格快速拖动到 tableView 中?【英文标题】:How to drag a static cell into tableView swift? 【发布时间】:2016-02-01 00:08:15 【问题描述】:我的故事板中有一个tableView
,我在其中添加了 4 个静态单元格,我的故事板看起来像:
我没有此 tableView
的任何数据源,因为我的单元格是静态的。
我使用下面的代码来拖动一个单元格,它工作正常,直到我滚动一个表格。
import UIKit
class TableViewController: UITableViewController
var sourceIndexPath: NSIndexPath = NSIndexPath()
var snapshot: UIView = UIView()
let longPress: UILongPressGestureRecognizer =
let recognizer = UILongPressGestureRecognizer()
return recognizer
()
override func viewDidLoad()
super.viewDidLoad()
longPress.addTarget(self, action: "longPressGestureRecognized:")
self.tableView.addGestureRecognizer(longPress)
self.tableView.allowsSelection = false
override func viewWillAppear(animated: Bool)
self.tableView.reloadData()
// MARK: UIGestureRecognizer
func longPressGestureRecognized(gesture: UILongPressGestureRecognizer)
let state: UIGestureRecognizerState = gesture.state
let location:CGPoint = gesture.locationInView(self.tableView)
if let indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(location)
switch(state)
case UIGestureRecognizerState.Began:
sourceIndexPath = indexPath
let cell: UITableViewCell = self.tableView .cellForRowAtIndexPath(indexPath)!
//take a snapshot of the selected row using helper method
snapshot = customSnapshotFromView(cell)
//add snapshot as subview, centered at cell's center
var center: CGPoint = cell.center
snapshot.center = center
snapshot.alpha = 0.0
self.tableView.addSubview(snapshot)
UIView.animateWithDuration(0.25, animations: () -> Void in
center.y = location.y
self.snapshot.center = center
self.snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05)
self.snapshot.alpha = 0.98
cell.alpha = 0.0
, completion: (finished) in
cell.hidden = true
)
case UIGestureRecognizerState.Changed:
let cell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
var center: CGPoint = snapshot.center
center.y = location.y
snapshot.center = center
print("location \(location.y)")
//is destination valid and is it different form source?
if indexPath != sourceIndexPath
//update data source
//I have commented this part because I am not using any dataSource.
// self.customArray.exchangeObjectAtIndex(indexPath.row, withObjectAtIndex: sourceIndexPath.row)
//move the row
self.tableView.moveRowAtIndexPath(sourceIndexPath, toIndexPath: indexPath)
//and update source so it is in sync with UI changes
sourceIndexPath = indexPath
if (location.y < 68) || (location.y > 450)
print("cancelled")
self.snapshot.alpha = 0.0
cell.hidden = false
UIView.animateWithDuration(0.10, animations: () -> Void in
self.snapshot.center = cell.center
self.snapshot.transform = CGAffineTransformIdentity
self.snapshot.alpha = 0.0
//undo fade out
cell.alpha = 1.0
, completion: (finished) in
self.snapshot.removeFromSuperview()
)
case UIGestureRecognizerState.Ended:
//clean up
print("ended")
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
cell.hidden = false
UIView.animateWithDuration(0.25, animations: () -> Void in
self.snapshot.center = cell.center
self.snapshot.transform = CGAffineTransformIdentity
self.snapshot.alpha = 0.0
//undo fade out
cell.alpha = 1.0
, completion: (finished) in
self.snapshot.removeFromSuperview()
)
break
default:
break
else
gesture.cancelsTouchesInView = true
func customSnapshotFromView(inputView: UIView) -> UIView
// Make an image from the input view.
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0)
inputView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
// Create an image view.
let snapshot = UIImageView(image: image)
snapshot.layer.masksToBounds = false
snapshot.layer.cornerRadius = 0.0
snapshot.layer.shadowOffset = CGSize(width: -5.0, height: 0.0)
snapshot.layer.shadowRadius = 5.0
snapshot.layer.shadowOpacity = 0.4
return snapshot
当我拖动后滚动时,它看起来像:
如您所见,单元格不再出现。我想拖放静态单元格,我想保存它的位置,这样我滚动时就不会再次重新排列。
Sample 项目了解更多信息。
这只是一个演示项目,但我在单元格中添加了许多元素,每个单元格都有不同的 UI。
【问题讨论】:
我不认为没有UITableViewDataSource
协议你可以接近它
【参考方案1】:
有一个库可以用非常相似的方法完成您想要做的事情。它被称为FMMoveTableView,但它适用于具有数据源的单元格。
我认为导致您的问题的原因是当您移动单元格然后从情节提要中滚动数据源时不再与表格同步,因此您的单元格对象无法重绘。
我认为你应该这样实现你的表:
-
使您的 4 个单元格自定义单元格。
每个子类。
创建一个编号为 1 到 4 的数组
长拖拽数组重新排序
覆盖
cellForRowAtIndexPath
以显示正确数字的正确单元格
【讨论】:
是的,我可以做到这一点,但如果可能的话,我想用静态单元格做到这一点.. :)【参考方案2】:您可以从 uitableview 代表中拖动 uitableview 单元...... 1) 在其委托中将表格视图编辑样式设置为无。
2) 实现表格视图委托以启用单元格的拖动,即 canMoveRowAtIndexPath 方法...
【讨论】:
【参考方案3】:您可以创建多个动态单元格。 您只需将具有正确标识符的单元格出列即可。
【讨论】:
你能举个例子吗? 而不是创建 4 个静态单元格。创建 4 个动态单元并将 tableView 的数据源连接到您的 TVC。并在 cellForRowAtIndexPathMethod 中将相应的单元格出列。例如:给单元格提供这些标识符:单元格1、单元格2、单元格3、单元格4。然后在 cellForRow 方法中执行此操作:'return tableView.dequeueReusableCellWithIdentifier("cell(indexPath.row)")' 您还需要保存单元格顺序数组。然后 dequeue 方法看起来像这样 return tableView.dequeueReusableCellWithIdentifier("cell(cellOrderArray[indexPath.row])")【参考方案4】:您这样做只是为了布局,也许UICollectionView
或定制的UIScrollView
可以完成这项工作?
无论如何,我有一个解决方案:
-
创建一个包含所有静态
UITableViewCell
s 的 IBOutlet 集合
创建索引列表来模拟“数据源”
覆盖cellForRowAtIndexPath
以使用您自己的索引列表进行绘制
更新列表顺序时,更新 indexList 以便视图“记住”此更改
这个表格视图控制器解释了一切:
class TableViewController: UITableViewController
@IBOutlet var outletCells: [UITableViewCell]!
var indexList = [Int]()
override func viewDidLoad()
super.viewDidLoad()
// Prepare a index list.
// We will move positions in this list instead
// of trying to move the view's postions.
for (index, _) in outletCells.enumerate()
indexList.append(index)
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// Use dynamic count, not needed I guess but
// feels better this way.
return outletCells.count
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
// Use the index path to get the true index and return
// the view on that index in our IBOutlet collection
let realIndexForPos = indexList[indexPath.row]
return outletCells[realIndexForPos]
@IBAction func onTap(sender: AnyObject)
// Simulating your drag n drop stuff here... :)
let swapThis = 1
let swapThat = 2
tableView.moveRowAtIndexPath(NSIndexPath(forItem: swapThis, inSection: 0), toIndexPath: NSIndexPath(forItem: swapThat, inSection: 0))
// Update the indexList as this is the "data source"
// Do no use moveRowAtIndexPath as this is never triggred
// This one line works: swap(&indexList[swapThis], &indexList[swapThat])
// But bellow is easier to understand
let tmpVal = indexList[swapThis]
indexList[swapThis] = indexList[swapThat]
indexList[swapThat] = tmpVal
要创建IBOutlet
,请使用界面生成器。
在每个表视图单元格上使用Referencing Outlet Collection
,并将每个单元格拖到控制器代码中的相同@IBOutlet
。
【讨论】:
嗨,我已将源和目标索引路径存储在 nsmutable 数组中,如何在打开应用程序时存储和重新排序我的 tableview 单元格。 func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) let item : String = dataHolder[sourceIndexPath.row]; dataHolder.removeAtIndex(sourceIndexPath.row); dataHolder.insert(item, atIndex: destinationIndexPath.row) toArray.addObject(destinationIndexPath.row) fromArray.addObject(sourceIndexPath.row)以上是关于如何将静态单元格快速拖动到 tableView 中?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS Swift 中将选定的 tableView 单元格保存到数组中?
tableview 单元格我们如何快速调整单元格的大小以及图像和标签
如何获取在情节提要中为 tableView 静态单元格设置的预设高度?
为啥在将单元格插入带有静态单元格的表格视图时需要 tableView(_:indentationLevelForRowAt:)