UITableView 행 재정렬을 섹션으로 제한하는 방법


121

나는 이것 위에 내 머리를 치고 있었고, 구글은 아무것도 밝히지 않았다. 나는 결국 그것을 해결했고 다음 사람을 위해 여기에 쓸 것이라고 생각했습니다.

당신은이 UITableView여러 섹션으로. 각 섹션은 동종이지만 테이블 전체는 이기종입니다. 따라서 섹션 내에서 행을 재정렬 할 수 있지만 섹션 간에는 순서를 변경할 수 없습니다 . 아마도 한 섹션 만 다시 정렬 할 수 있기를 원할 수도 있습니다 (제 경우). 내가 그랬던 것처럼에서 UITableViewDataSourceDelegate섹션간에 행을 이동할 수있는시기에 대한 알림을 찾을 수 없습니다. 행 이동을 시작할 때 하나 (괜찮음)를 얻고 이미 이동했으면 하나를 얻고 내부 항목과 동기화 할 기회를 얻습니다. 도움이되지 않습니다.

그렇다면 섹션 간의 재정렬을 어떻게 방지 할 수 있습니까?

내가 한 일을 별도의 답변으로 게시하고 다른 사람이 더 나은 답변을 게시 할 수 있도록 열어 두겠습니다!


1
"행 이동을 시작할 때 알림이 표시됩니다"라고 말할 때 어떤 알림을 참조하고 있습니까? 나는 하나를 보지는 않지만 세포 재정렬이 시작되는 때를 식별하기를 희망합니다.
TomSwift

답변:


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

1
Xamarin에서 래퍼 메서드는 UIKit.UITableViewController.CustomizeMoveTarget궁금한 사람을위한입니다.
벙커 다이브

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! 그것이 틀렸다는 말이 아니라 실제로 이것보다 더 복잡한 것인지 궁금합니다.
Billy Gray

해당 행이 설정되지 않은 경우에도 다른 섹션의 행을 드래그 할 수 있습니다. 하지만 강제로 다른 사람에게 보일 때.? 어떤 생각
샌디

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
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.