Як обмежити редакцію рядка UITableView до розділу


121

Я бив головою над цим, і Google не повертав нічого. Я врешті-решт розробив це і подумав, що напишу це заради наступної людини.

У вас є UITableViewкілька розділів. Кожен розділ є однорідним, але загальна таблиця неоднорідною. Тож ви можете дозволити переупорядкування рядків у розділі, але не через розділи. Можливо, ви навіть хочете, щоб хотіли, щоб один розділ взагалі був перезавантажений (це був мій випадок). Якщо ви шукаєте, як я був, у UITableViewDataSourceDelegateвас не знайдеться повідомлення про те, коли воно збирається перенести рядок між розділами. Ви отримуєте такий, коли він починає переміщувати рядок (що добре), і той, коли він уже переміщений, і ви отримуєте шанс синхронізувати свої внутрішні речі. Не корисно.

Тож як можна запобігти повторним замовленням між розділами?

Я опублікую те, що я зробив, як окрему відповідь, залишаючи відкритим для когось іншого, щоб розмістити ще кращу відповідь!


1
На яке сповіщення ви посилаєтесь, говорячи "ви отримуєте одне, коли воно починає переміщувати рядок"? Я не бачу такого, але сподіваюся розрізнити, коли почнеться перенастроювання клітин.
TomSwift

Відповіді:


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

Чи є спосіб запобігти автоматичному прокручуванню таблиці (під час перетягування комірки) за межами дозволеного розділу?
Палімондо

1
У Xamarin метод обгортки є UIKit.UITableViewController.CustomizeMoveTargetдля всіх, хто цікавиться.
bunkerdive

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! не кажучи, що це неправильно, просто мені цікаво, чи насправді це складніше, ніж це.
Біллі Грей

Я можу перетягнути рядок в інший розділ, навіть якщо цей рядок не встановлюється туди. але це видно коли іншим насильно. будь-яка ідея
Сенді

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
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.