Cách giới hạn việc sắp xếp lại hàng UITableView cho một phần


121

Tôi đâm đầu vào cái này, và google chẳng thấy gì cả. Cuối cùng tôi đã tìm ra nó và nghĩ rằng tôi sẽ viết nó lên đây vì lợi ích của người tiếp theo.

Bạn có một UITableViewvới nhiều phần. Mỗi phần là đồng nhất, nhưng bảng tổng thể là không đồng nhất. Vì vậy, bạn có thể muốn cho phép sắp xếp lại các hàng trong một phần, nhưng không phải trên các phần. Có thể bạn chỉ muốn một phần có thể sắp xếp lại được (đó là trường hợp của tôi). Nếu bạn đang tìm kiếm, giống như tôi, UITableViewDataSourceDelegatebạn sẽ không tìm thấy thông báo khi nó sắp cho phép bạn di chuyển một hàng giữa các phần. Bạn nhận được một khi nó bắt đầu di chuyển một hàng (điều đó tốt) và một khi nó đã di chuyển nó và bạn có cơ hội đồng bộ hóa với nội dung bên trong của mình. Không hữu dụng.

Vì vậy, làm thế nào bạn có thể ngăn chặn việc tái đặt hàng giữa các phần?

Tôi sẽ đăng những gì tôi đã làm dưới dạng một câu trả lời riêng biệt, để ngỏ cho người khác đăng câu trả lời thậm chí còn tốt hơn!


1
Bạn đang đề cập đến thông báo nào khi nói "bạn nhận được một thông báo khi nó bắt đầu di chuyển một hàng"? Tôi không nhìn thấy một cái nhưng tôi hy vọng sẽ phân biệt được thời điểm bắt đầu sắp xếp lại ô.
TomSwift,

Câu trả lời:


181

Việc triển khai này sẽ ngăn việc sắp xếp lại bên ngoài phần ban đầu như câu trả lời của Phil, nhưng nó cũng sẽ gắn bản ghi vào hàng đầu tiên hoặc cuối cùng của phần, tùy thuộc vào nơi kéo đi, thay vì nơi bắt đầu.

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

Có cách nào để ngăn bảng tự động cuộn (trong khi kéo một ô) bên ngoài phần được phép không?
Palimondo

1
Trong Xamarin, phương pháp wrapper là UIKit.UITableViewController.CustomizeMoveTargetđối với bất kỳ ai thắc mắc.
bunkerdive

74

Thực sự là đủ đơn giản.

UITableViewDelegate có phương thức:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

Điều này được gọi trong khi người dùng đang di chuột qua một điểm rơi tiềm năng. Bạn có cơ hội để nói, "không! Đừng thả nó ở đó! Thay vào đó, hãy thả nó qua đây". Bạn có thể trả về một đường dẫn chỉ mục khác cho đường dẫn được đề xuất.

Tất cả những gì tôi đã làm là kiểm tra xem các chỉ số phần có khớp nhau không. Nếu họ làm thì tuyệt vời, hãy trả lại đường dẫn được đề xuất. nếu không, hãy trả về đường dẫn nguồn. Điều này cũng ngăn chặn độc đáo các hàng trong các phần khác thậm chí di chuyển ra khỏi đường khi bạn kéo - và hàng được kéo sẽ trở lại vị trí ban đầu của nó khi bạn cố gắng di chuyển nó sang phần khác.


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

Thực hiện chính xác điều này khiến một số lỗi hiển thị thực sự kỳ lạ xảy ra trên thiết lập của tôi và nó khác biệt đáng kể so với mã ví dụ của chính apple về cách thực hiện điều này. FWIW! không nói nó sai, chỉ là tôi tự hỏi liệu nó có thực sự phức tạp hơn thế này không.
Billy Grey,

Tôi có thể kéo hàng trong phần khác ngay cả khi hàng đó không được đặt ở đó. nhưng nó hiển thị khi nào đối với người khác một cách mạnh mẽ.? bất kỳ ý tưởng nào
Sandy

27

Phiên bản nhanh chóng Swifty của câu trả lời của Jason dành cho những người lười biếng:

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
}

Swift 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

Bạn có thể ngăn chặn sự di chuyển của các hàng giữa các phần bằng cách sử dụng phương pháp dưới đây. Chỉ cần không cho phép bất kỳ chuyển động nào giữa các phần. Bạn thậm chí có thể kiểm soát chuyển động của hàng cụ thể trong một phần. ví dụ: hàng cuối cùng trong một Phần.

Đây là ví dụ:

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

Swift 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

Hơn @Jason Harwig, mã bên dưới hoạt động chính xác.

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

Để không thay đổi vị trí giữa các phần Swift3

override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
    if originalIndexPath.section != proposedIndexPath.section
    {
        return originalIndexPath
    }
    else
    {
        return proposedIndexPath
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.