Bagaimana membatasi pengurutan ulang baris UITableView ke suatu bagian

121

Kepalaku sedang memikirkan yang satu ini, dan Google tidak menemukan apa pun. Saya akhirnya berhasil dan berpikir saya akan menulisnya di sini demi orang berikutnya.

Anda memiliki UITableViewdengan banyak bagian. Setiap bagian homogen, tetapi tabel secara keseluruhan heterogen. Jadi, Anda mungkin ingin mengizinkan pengurutan ulang baris dalam suatu bagian, tetapi tidak di seluruh bagian. Mungkin Anda bahkan hanya ingin satu bagian dapat disusun ulang sama sekali (itu kasus saya). Jika Anda melihat, seperti saya sebelumnya, di UITableViewDataSourceDelegateAnda tidak akan menemukan pemberitahuan tentang kapan akan membiarkan Anda memindahkan baris antar bagian. Anda mendapatkannya ketika mulai memindahkan baris (yang bagus) dan satu ketika sudah dipindahkan dan Anda mendapat kesempatan untuk menyinkronkan dengan barang-barang internal Anda. Tidak membantu.

Jadi bagaimana Anda dapat mencegah pemesanan ulang antar bagian?

Saya akan memposting apa yang saya lakukan sebagai jawaban terpisah, membiarkannya terbuka bagi orang lain untuk memposting jawaban yang lebih baik!

philsquared
sumber
1
Notifikasi mana yang Anda maksud saat Anda mengatakan "Anda mendapatkannya saat mulai berpindah baris"? Saya tidak melihatnya, tetapi saya berharap untuk mengetahui kapan penataan ulang sel dimulai.
TomSwift

Jawaban:

181

Implementasi ini akan mencegah pengurutan ulang di luar bagian asli seperti jawaban Phil, tetapi itu juga akan menjepret rekaman ke baris pertama atau terakhir dari bagian, tergantung di mana seret pergi, bukan di mana itu dimulai.

- (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;
}
Jason Harwig
sumber
Adakah cara untuk mencegah tabel menggulir otomatis (saat menyeret sel) di luar bagian yang diizinkan?
Palimondo
1
Di Xamarin, metode pembungkusnya adalah UIKit.UITableViewController.CustomizeMoveTarget, bagi siapa pun yang bertanya-tanya.
bunkerdive
74

Cukup sederhana, sungguh.

UITableViewDelegate memiliki metode:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

Ini dipanggil saat pengguna mengarahkan kursor ke titik penurunan potensial. Anda mendapat kesempatan untuk berkata, "tidak! Jangan jatuhkan di sana! Jatuhkan di sini saja". Anda dapat mengembalikan jalur indeks yang berbeda ke yang diusulkan.

Yang saya lakukan hanyalah memeriksa apakah indeks bagian cocok. Jika mereka berhasil maka bagus, kembalikan jalan yang diusulkan. jika tidak, kembalikan jalur sumber. Ini juga dengan baik mencegah baris di bagian lain bahkan keluar dari jalan saat Anda menyeret - dan baris yang diseret akan kembali ke posisi semula saat Anda mencoba memindahkannya ke bagian lain.


- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    if( sourceIndexPath.section != proposedDestinationIndexPath.section )
    {
        return sourceIndexPath;
    }
    else
    {
        return proposedDestinationIndexPath;
    }
}
philsquared
sumber
Melakukan hal ini dengan tepat menyebabkan beberapa bug tampilan yang benar-benar aneh terjadi di pengaturan saya, dan ini sangat berbeda dari kode contoh Apple sendiri tentang cara melakukan ini. FWIW! tidak mengatakan itu salah, hanya saja saya bertanya-tanya apakah sebenarnya lebih rumit dari ini.
Billy Grey
Saya dapat menyeret baris di bagian lain meskipun baris itu tidak diatur di sana. tapi itu terlihat saat memaksa lainnya.? ada ide
Sandy
27

Versi swifty swift dari jawaban Jason untuk kamu para pemalas:

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

Cepat 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
}
Alexander dari Norwegia
sumber
7

Anda dapat mencegah pergerakan baris di antara bagian menggunakan metode di bawah ini. Hanya saja, jangan biarkan ada gerakan di antara bagian tersebut. Anda bahkan dapat mengontrol pergerakan baris tertentu dalam suatu bagian. mis. baris terakhir dalam Bagian.

Berikut contohnya:

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

Cepat 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
}
Henry
sumber
3

Dari pada @Jason Harwig, kode di bawah ini berfungsi dengan benar.

- (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;
    }
Bkillnest
sumber
1

Untuk tidak mengubah posisi antara bagian Swift3

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