UITableView行の並べ替えをセクションに制限する方法


121

私はこれに頭をぶつけて、グーグルは何も起こらなかった。私は最終的にそれを解決し、次の人のためにここに書こうと思いました。

あなたは持っているUITableView複数のセクションで。各セクションは同種ですが、テーブル全体は異種です。あなたは、セクション内の行の並べ替えではなく、許可したい場合がありますので渡っセクション。たぶん、1つのセクションだけを並べ替え可能にしたいだけかもしれません(それが私の場合でした)。私がそうであるように、あなたが探しているのならUITableViewDataSourceDelegate、セクション間で行を移動させようとしているときの通知が見つかりません。行の移動を開始したときに1つ(これは問題ありません)と、既に移動したときに1つ取得し、内部のものと同期する機会を得ます。役に立たなかった。

では、どうすればセクション間の再注文を防ぐことができますか?

私がやったことを別の回答として投稿し、他の人がより良い回答を投稿できるようにしておきます!


1
「行の移動を開始すると通知が届きます」と言ったとき、どの通知を参照していますか?私はそれを見ていませんが、細胞の再配列がいつ始まるかを見極めたいと思っています。
TomSwift 2012年

回答:


181

この実装は、フィルの回答のように元のセクションの外での並べ替えを防ぎますが、ドラッグがどこから始まったかではなく、どこにドラッグしたかによって、レコードをセクションの最初または最後の行にスナップします。

- (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 2012

1
Xamarinでは、ラッパーメソッドはUIKit.UITableViewController.CustomizeMoveTargetです。
バンカーダイブ2017

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

これを正確に行うと、セットアップで本当に奇妙な表示のバグが発生します。これを行う方法については、アップル独自のサンプルコードとは著しく異なります。FWIW!間違っていると言っているのではなく、実際にこれよりも複雑なのかと思います。
ビリーグレイ

その行が設定されていなくても、他のセクションの行をドラッグできます。しかし、それはいつ他の人に強制的に表示されますか?任意のアイデア
Sandy

27

怠惰な人々のためのジェイソンの回答の迅速な迅速なバージョン:

スイフト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
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.