如何限制UITableView行重新排序到一节


121

我为此感到头疼,而Google却一无所获。我最终解决了这个问题,并认为我为了下一个人在这里写下来。

您有UITableView多个部分。每个部分都是同质的,但表的整体是异构的。因此,您可能希望允许对部分中的行进行重新排序,但不能部分进行重新排序。也许您甚至只希望一个部分可以重新排序(这就是我的情况)。如果您像我一样看的话,UITableViewDataSourceDelegate您将找不到关于何时要在各节之间移动行的通知。当它开始移动一行时,您会得到一个(这很好),而当它已经移动行时,您就会得到一个,并且您有机会与内部内容进行同步。没有帮助。

那么如何防止各节之间重新排序呢?

我会将所做的工作作为单独的答案发布,让其他人可以发布更好的答案!


1
当您说“当它开始移动一行时,您会得到一个”时,您指的是哪个通知?我没看到一个,但希望能辨别何时开始进行单元重新排序。
TomSwift 2012年

Answers:


181

此实现将防止像Phil的答案那样在原始部分之外进行重新排序,但也会将记录捕捉到部分的第一行或最后一行,具体取决于拖动的位置而不是拖动的起始位置。

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
  if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
    NSInteger row = 0;
    if (sourceIndexPath.section < proposedDestinationIndexPath.section) {
      row = [tableView numberOfRowsInSection:sourceIndexPath.section] - 1;
    }
    return [NSIndexPath indexPathForRow:row inSection:sourceIndexPath.section];     
  }

  return proposedDestinationIndexPath;
}

有没有一种方法可以防止表格在允许的部分之外自动滚动(拖动单元格时)?
Palimondo '04 -4-8

1
在Xamarin中UIKit.UITableViewController.CustomizeMoveTarget,对于任何想知道的人,wrapper方法都是。
bunkerdive

74

确实很简单。

UITableViewDelegate具有以下方法:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

当用户将鼠标悬停在潜在的下降点上时,将调用此方法。您将有机会说:“不!不要把它放在这里!而是把它放在这里”。您可以将其他索引路径返回到建议的索引路径。

我所做的只是检查部分索引是否匹配。如果他们做的很好,请返回建议的路径。如果不是,则返回源路径。这也很好地防止了其他部分中的行甚至在您拖动时移开-并且被拖动的行将恢复到您尝试将其移动到另一部分时的原始位置。


- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    if( sourceIndexPath.section != proposedDestinationIndexPath.section )
    {
        return sourceIndexPath;
    }
    else
    {
        return proposedDestinationIndexPath;
    }
}

正是这样做会导致在我的设置中发生一些真正奇怪的显示错误,并且与Apple自己的示例代码在执行此操作方面有明显不同。FWIW!并不是说这是错误的,只是我想知道它是否真的比这更复杂。
比利·格雷

我可以拖动其他部分中的行,即使该行未在那里设置。但是何时强制使用其他方法还是可见的。任何想法
Sandy'2

27

Jason的答案的快速版本懒惰的人:

斯威夫特3、4和5

override func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
    if sourceIndexPath.section != proposedDestinationIndexPath.section {
        var row = 0
        if sourceIndexPath.section < proposedDestinationIndexPath.section {
            row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1
        }
        return IndexPath(row: row, section: sourceIndexPath.section)
    }
    return proposedDestinationIndexPath
}

斯威夫特1&2

override func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
    if sourceIndexPath.section != proposedDestinationIndexPath.section {
        var row = 0
        if sourceIndexPath.section < proposedDestinationIndexPath.section {
            row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1
        }
        return NSIndexPath(forRow: row, inSection: sourceIndexPath.section)
    }
    return proposedDestinationIndexPath
}

7

您可以使用以下方法防止行在节之间移动。只是不允许部分之间有任何运动。您甚至可以控制节中特定行的移动。例如,节中的最后一行。

这是示例:

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {

    // Do not allow any movement between section
    if ( sourceIndexPath.section != proposedDestinationIndexPath.section) {
        return sourceIndexPath;
    }
    // You can even control the movement of specific row within a section. e.g last row in a     Section

    // Check if we have selected the last row in section
    if (sourceIndexPath.row < sourceIndexPath.length) {
        return proposedDestinationIndexPath;
    } 
    else {
        return sourceIndexPath;
    }
}

7

斯威夫特3:

override func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
    if sourceIndexPath.section != proposedDestinationIndexPath.section {
        var row = 0
        if sourceIndexPath.section < proposedDestinationIndexPath.section {
            row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1
        }
        return IndexPath(row: row, section: sourceIndexPath.section)
    }
    return proposedDestinationIndexPath
}

3

比@Jason Harwig,下面的代码可以正常工作。

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
    {
      if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
        NSInteger row = 0;
        if (sourceIndexPath.section < proposedDestinationIndexPath.section) {
          row = [tableView numberOfRowsInSection:sourceIndexPath.section] - 1;
        }
        return [NSIndexPath indexPathForRow:row inSection:sourceIndexPath.section];     
      }

      return proposedDestinationIndexPath;
    }

1

用于不更改部分之间的位置Swift3

override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
    if originalIndexPath.section != proposedIndexPath.section
    {
        return originalIndexPath
    }
    else
    {
        return proposedIndexPath
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.