Переупорядочение UITableView без контроля порядка

Мне нужно, чтобы пользователь мог переупорядочить UITableView таким образом: он касается ячейки в течение заданного периода (например, 1 секунду), затем он может перетаскивать ее по другим ячейкам.

Я знаю, как реализовать обнаружение "длинного касания" с помощью распознавателя жестов, но лучший способ реализовать функцию перетаскивания без использования управления переупорядочением (пользователь должен перетаскивать ячейку из любой точки ячейки, не только от контроля переупорядочения)?

Ответ 1

Это старый вопрос, но вот решение, которое протестировало и работало с iOS 8 через 11.

В подклассе UITableViewCell попробуйте следующее:

class MyTableViewCell: UITableViewCell {
    weak var reorderControl: UIView?

    override func layoutSubviews() {
        super.layoutSubviews()

        // Make the cell `contentView` as big as the entire cell.
        contentView.frame = bounds

        // Make the reorder control as big as the entire cell 
        // so you can drag from everywhere inside the cell.
        reorderControl?.frame = bounds
    }

    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: false)
        if !editing || reorderControl != nil {
            return
        }

        // Find the reorder control in the cell subviews.
        for view in subviews {
            let className = String(describing: type(of:view))
            if className == "UITableViewCellReorderControl" {

                // Remove its subviews so that they don't mess up
                // your own content appearance.
                for subview in view.subviews {
                    subview.removeFromSuperview()
                }

                // Keep a weak reference to it for `layoutSubviews()`.
                reorderControl = view

                break
            }
        }
    }
}

Это близко к Сенсационное первое предложение, но статья, на которую он ссылается, больше не работает.

Что вы делаете, это сделать управление переупорядочением и представление содержимого ячейки большим, чем целая ячейка, когда она редактируется. Таким образом, вы можете перетаскивать из любой точки ячейки, и ваше содержимое занимает все пространство, как будто ячейка вообще не редактировалась.

Важнейшим недостатком этого является то, что вы изменяете структуру представления системной ячейки и ссылаетесь на частный класс (UITableViewCellReorderControl). Кажется, он работает правильно для всех последних версий iOS, но вы должны убедиться, что он все еще действителен каждый раз, когда выйдет новая ОС.

Ответ 2

Я решил вопрос о следующих шагах:

  • Прикрепите распознаватель жестов к UITableView.
  • Определите, какая ячейка была нажата "длинным касанием". В этот момент создайте снимок выбранной ячейки, поместите ее в UIImageView и поместите ее в UITableView. Координаты UIImageView должны отображать выбранную ячейку относительно UITableView (моментальный снимок выбранной ячейки должен перекрывать выбранную ячейку).
  • Сохранить индекс выбранной ячейки, удалить выбранную ячейку и перезагрузить UITableView.
  • Отключить прокрутку для UITableView. Теперь вам нужно изменить рамку моментального снимка UIImageView, когда вы перетащите ячейку. Вы можете сделать это в методе touchesMoved.
  • Создайте новую ячейку и перезагрузите UITableView (вы уже сохранили индекс), когда пользовательский палец покидает экран.
  • Удалить снимок UIImageView.

Но это было непросто сделать.

Ответ 3

В статье Переупорядочение UITableViewCell из любой точки касания обсуждается этот точный сценарий.

По существу вы делаете следующее:

  • Найдите UITableViewCellReorderControl (частный класс).
  • Разверните его, чтобы он охватывал всю ячейку.
  • Скрыть его.
  • Теперь пользователь сможет перетаскивать ячейку из любого места.

Другое решение, "Поваренная книга: перемещение табличных ячеек с длинным жестом нажатия" , дает такой же эффект, делая следующее:

  • Добавьте в табличный вид длинный идентификатор распознавания жестов.
  • Создайте моментальный снимок ячейки при перетаскивании ячейки.
  • Когда ячейка перетаскивается, переместите снимок вокруг и вызовите -[UITableView moveRowAtIndexPath:toIndexPath:].
  • Когда этот жест заканчивается, скройте снимок ячейки.

Ответ 5

Я знаю, что это вопрос о UITableView. Но я закончил с решением использовать UICollectionView, а не UITableView для реализации переупорядочения longtap. Это легко и просто.