UITableView satırını bir bölümle yeniden sıralama nasıl sınırlanır


121

Bunun üzerine kafamı vuruyordum ve google hiçbir şey göstermiyordu. Sonunda bunu çözdüm ve bir sonraki kişinin iyiliği için buraya yazacağımı düşündüm.

UITableViewBirden çok bölümü olan bir alanınız var. Her bölüm homojendir, ancak genel tablo heterojendir. Bir bölümdeki satır yeniden sipariş, ancak izin vermek isteyebilirsiniz Yani genelinde bölümler. Belki de sadece bir bölümün yeniden sıralanmasını istiyorsunuz (bu benim durumumdu). Benim gibi bakıyorsanız, UITableViewDataSourceDelegatebölümler arasında bir satırı taşımanıza izin vermek üzere olduğu zaman için bir bildirim bulamazsınız. Bir satırı taşımaya başladığında (ki bu iyi) bir tane alırsınız ve zaten taşındığında bir tane alırsınız ve iç öğelerinizle senkronize etme şansı elde edersiniz. Yararlı değil.

Peki bölümler arasında yeniden sipariş verilmesini nasıl önleyebilirsiniz?

Yaptığım şeyi ayrı bir cevap olarak göndereceğim ve başka birinin daha iyi bir cevap göndermesi için açık bırakacağım!


1
"Bir satırı hareket ettirmeye başladığında alırsın" derken hangi bildirimi kastediyorsun? Bir tane görmüyorum ama hücre yeniden düzenlemenin ne zaman başladığını fark etmeyi umuyorum.
TomSwift

Yanıtlar:


181

Bu uygulama, Phil'in cevabı gibi orijinal bölümün dışında yeniden sıralamayı engelleyecektir, ancak aynı zamanda sürüklemenin başladığı yer yerine nereye gittiğine bağlı olarak kaydı bölümün ilk veya son satırına da yapıştıracaktır.

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

Tablonun, izin verilen bölümün dışında otomatik olarak (bir hücre sürüklenirken) kaydırılmasını önlemenin bir yolu var mı?
Palimondo

1
Xamarin'de, UIKit.UITableViewController.CustomizeMoveTargetmerak eden herkes için sarmalayıcı yöntemi vardır .
bunkerdive

74

Yeterince basit, gerçekten.

UITableViewDelegate yöntemi şu şekildedir:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

Bu, kullanıcı potansiyel bir bırakma noktasının üzerine gelirken çağrılır. "Hayır! Oraya düşürmeyin! Onun yerine buraya bırakın" deme şansınız var. Önerilen dizine farklı bir dizin yolu döndürebilirsiniz.

Tek yaptığım, bölüm indekslerinin eşleşip eşleşmediğini kontrol etmekti. Başarılı olurlarsa, önerilen yola geri dönün. değilse, kaynak yolunu döndürün. Bu aynı zamanda, diğer bölümlerdeki satırların siz sürüklerken yolun dışına çıkmasını bile güzel bir şekilde önler - ve sürüklenen satır, siz onu başka bir bölüme taşımaya çalıştığınız orijinal konumuna geri dönecektir.


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

Tam olarak bunu yapmak, kurulumumda bazı gerçekten garip görüntü hatalarının oluşmasına neden oluyor ve bu, Apple'ın bunun nasıl yapılacağına dair kendi örnek kodundan oldukça farklı. FWIW! bunun yanlış olduğunu söylemiyorum, sadece bundan daha karmaşık olup olmadığını merak ediyorum.
Billy Gray

O satır orada ayarlanmasa bile başka bölümdeki satırı sürükleyebilirim. ama diğerlerine ne zaman zorla görünür.? herhangi bir fikir
Sandy

27

Tembel insanlar için Jason'ın cevabının hızlı ve hızlı versiyonu:

Hızlı 3, 4 ve 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
}

Hızlı 1 ve 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

Aşağıdaki yöntemi kullanarak satırların bölümler arasında hareket etmesini engelleyebilirsiniz. Sadece bölümler arasında herhangi bir harekete izin vermeyin. Hatta bir bölüm içindeki belirli satırın hareketini bile kontrol edebilirsiniz. örneğin bir Bölümdeki son satır.

İşte örnek:

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

@ Jason Harwig yerine, aşağıdaki kod doğru çalışıyor.

- (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 bölümleri arasında pozisyon değiştirmemek için

override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
    if originalIndexPath.section != proposedIndexPath.section
    {
        return originalIndexPath
    }
    else
    {
        return proposedIndexPath
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.