【问题标题】:How to limit UITableView row reordering to a section如何将 UITableView 行重新排序限制为一个部分
【发布时间】:2010-10-25 09:30:30
【问题描述】:

我对此一头雾水,而谷歌却一无所获。 我最终解决了这个问题,并认为我会把它写在这里以供下一个人使用。

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

那么如何防止部分之间重新订购?

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

【问题讨论】:

  • 当你说“当它开始移动一行时你得到一个”时,你指的是哪个通知?我没有看到,但我希望能够辨别单元格重新排序何时开始。

标签: ios iphone uitableview cocoa-touch


【解决方案1】:

真的很简单。

UITableViewDelegate 有方法:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

当用户将鼠标悬停在一个潜在的放置点上时会调用它。 你有机会说,“不!不要把它丢在那里!把它丢在这里”。您可以将不同的索引路径返回到建议的路径。

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


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

【讨论】:

  • 这样做会导致在我的设置中出现一些真正奇怪的显示错误,这与苹果自己的示例代码如何执行此操作有显着不同。 FWIW!不是说错了,只是我想知道它是否真的比这更复杂。
  • 我可以在其他部分拖动行,即使该行没有在那里设置。但它是可见的什么时候强行其他。?任何想法
【解决方案2】:

此实现将防止像 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;
}

【讨论】:

  • 有没有办法防止表格在允许的部分之外自动滚动(同时拖动单元格)?
  • 在 Xamarin 中,包装方法是 UIKit.UITableViewController.CustomizeMoveTarget,任何人都想知道。
【解决方案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;
    }

【讨论】:

    【解决方案4】:

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

    示例如下:

    - (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;
        }
    }
    

    【讨论】:

      【解决方案5】:

      Jason 为你懒惰的人提供的 Swifty 快速版本:

      Swift 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
      }
      

      【讨论】:

      • 复制,粘贴。跑了,很喜欢。回来。谢谢,这感觉很内疚,但我接受! ;)
      • 我正在使用 Swift 5,我在这里感到困惑。我们是否需要override 关键字?因为,如果我使用 override 关键字,我会得到编译器错误。
      【解决方案6】:

      斯威夫特 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
      }
      

      【讨论】:

        【解决方案7】:

        为了不改变部分之间的位置Swift3

        override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
            if originalIndexPath.section != proposedIndexPath.section
            {
                return originalIndexPath
            }
            else
            {
                return proposedIndexPath
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2018-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-27
          相关资源
          最近更新 更多