Как перетащить статическую ячейку в tableView swift?

у меня есть один tableView в моей раскадровке, где я добавил в нее 4 статические ячейки, и моя раскадровка выглядит так:

enter image description here

у меня нет никаких данных для этого tableView потому что мои ячейки статичны.

и я использую ниже код для перетаскивания ячейки, и он работает нормально, пока я не прокручиваю таблицу.

import UIKit

class TableViewController: UITableViewController {

    var sourceIndexPath: NSIndexPath = NSIndexPath()
    var snapshot: UIView = UIView()
    let longPress: UILongPressGestureRecognizer = {
        let recognizer = UILongPressGestureRecognizer()
        return recognizer
        }()

    override func viewDidLoad() {
        super.viewDidLoad()

        longPress.addTarget(self, action: "longPressGestureRecognized:")
        self.tableView.addGestureRecognizer(longPress)

        self.tableView.allowsSelection = false
    }

    override func viewWillAppear(animated: Bool) {

        self.tableView.reloadData()
    }

    // MARK: UIGestureRecognizer
    func longPressGestureRecognized(gesture: UILongPressGestureRecognizer){

        let state: UIGestureRecognizerState = gesture.state
        let location:CGPoint = gesture.locationInView(self.tableView)
        if let indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(location){

            switch(state){

            case UIGestureRecognizerState.Began:
                sourceIndexPath = indexPath

                let cell: UITableViewCell = self.tableView .cellForRowAtIndexPath(indexPath)!

                //take a snapshot of the selected row using helper method
                snapshot = customSnapshotFromView(cell)

                //add snapshot as subview, centered at cell's center
                var center: CGPoint = cell.center
                snapshot.center = center
                snapshot.alpha  = 0.0
                self.tableView.addSubview(snapshot)
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    center.y = location.y
                    self.snapshot.center = center
                    self.snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05)
                    self.snapshot.alpha = 0.98
                    cell.alpha = 0.0
                    }, completion: { (finished) in
                        cell.hidden = true
                })

            case UIGestureRecognizerState.Changed:
                let cell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!

                var center: CGPoint = snapshot.center
                center.y = location.y
                snapshot.center = center
                print("location (location.y)")

                //is destination valid and is it different form source?
                if indexPath != sourceIndexPath{
                    //update data source
                    //I have commented this part because I am not using any dataSource.
//                    self.customArray.exchangeObjectAtIndex(indexPath.row, withObjectAtIndex: sourceIndexPath.row)
                    //move the row
                    self.tableView.moveRowAtIndexPath(sourceIndexPath, toIndexPath: indexPath)
                    //and update source so it is in sync with UI changes
                    sourceIndexPath = indexPath
                }

                if (location.y < 68) || (location.y > 450) {
                    print("cancelled")
                    self.snapshot.alpha = 0.0
                    cell.hidden = false
                    UIView.animateWithDuration(0.10, animations: { () -> Void in

                        self.snapshot.center = cell.center
                        self.snapshot.transform = CGAffineTransformIdentity
                        self.snapshot.alpha = 0.0
                        //undo fade out
                        cell.alpha = 1.0

                        }, completion: { (finished) in
                            self.snapshot.removeFromSuperview()
                    })
                }

            case UIGestureRecognizerState.Ended:
                //clean up
                print("ended")
                let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
                cell.hidden = false

                UIView.animateWithDuration(0.25, animations: { () -> Void in

                    self.snapshot.center = cell.center
                    self.snapshot.transform = CGAffineTransformIdentity
                    self.snapshot.alpha = 0.0
                    //undo fade out
                    cell.alpha = 1.0

                    }, completion: { (finished) in
                        self.snapshot.removeFromSuperview()
                })
                break

            default:
                break
            }
        }else{
            gesture.cancelsTouchesInView = true
        }
    }

    func customSnapshotFromView(inputView: UIView) -> UIView {

        // Make an image from the input view.
        UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0)
        inputView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();

        // Create an image view.
        let snapshot = UIImageView(image: image)
        snapshot.layer.masksToBounds = false
        snapshot.layer.cornerRadius = 0.0
        snapshot.layer.shadowOffset = CGSize(width: -5.0, height: 0.0)
        snapshot.layer.shadowRadius = 5.0
        snapshot.layer.shadowOpacity = 0.4

        return snapshot
    }

}

когда я прокручиваю после перетаскивания, это выглядит так:

enter image description here

как вы можете видеть мобильный больше не появляется. Я хочу перетащить статическую ячейку и сохранить ее положение, чтобы не переставлять ее при прокрутке.

пример для получения дополнительной информации.

Это всего лишь демо-проект, но я добавил много элементов в свою ячейку, и каждая ячейка имеет другой пользовательский интерфейс.

4 ответов


есть библиотека, которая делает именно то, что вы хотите сделать с очень похожим подходом. Это называется FMMoveTableView но это для ячеек с источником данных.

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

Я думаю, что вы должны реализовать свою таблицу таким образом:

  1. сделайте свои 4 ячейки пользовательскими ячейками.
  2. подкласса каждый.
  3. создайте массив с номерами от 1 до 4
  4. переупорядочить массив на длительный перетащить
  5. переопределить cellForRowAtIndexPath чтобы показать правильную ячейку для правильного числа

вы можете перетащить ячейку uitableview из делегатов UITableView ....... 1)Установите для стиля редактирования представления таблицы значение none в делегате.

2) реализовать делегат представления таблицы для включения перетаскивания ячейки i.e методы canMoveRowAtIndexPath...


вы можете создать несколько динамических ячеек. Вам просто нужно удалить ячейки с правильным идентификатором.


вы делаете это только для целей макета, возможно,UICollectionView или на заказ UIScrollView могут сделать эту работу?


тем не менее, у меня есть решение:

  1. создайте коллекцию IBOutlet, содержащую все ваши статические UITableViewCells
  2. Создайте список индексов для имитации "источника данных"
  3. переопределить cellForRowAtIndexPath рисовать, используя свой собственный список индексов
  4. при обновлении порядка списка обновите список индексов так, чтобы представление "помнит" это изменение

этот контроллер представления таблицы объясняет все это:

class TableViewController: UITableViewController {

  @IBOutlet var outletCells: [UITableViewCell]!
  var indexList = [Int]()

  override func viewDidLoad() {
    super.viewDidLoad()
    // Prepare a index list.
    // We will move positions in this list instead
    // of trying to move the view's postions.
    for (index, _) in outletCells.enumerate() {
      indexList.append(index)
    }
  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Use dynamic count, not needed I guess but
    // feels better this way.
    return outletCells.count
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Use the index path to get the true index and return
    // the view on that index in our IBOutlet collection
    let realIndexForPos = indexList[indexPath.row]
    return outletCells[realIndexForPos]
  }

  @IBAction func onTap(sender: AnyObject) {
    // Simulating your drag n drop stuff here... :)
    let swapThis = 1
    let swapThat = 2

    tableView.moveRowAtIndexPath(NSIndexPath(forItem: swapThis, inSection: 0), toIndexPath: NSIndexPath(forItem: swapThat, inSection: 0))

    // Update the indexList as this is the "data source"
    // Do no use moveRowAtIndexPath as this is never triggred
    // This one line works: swap(&indexList[swapThis], &indexList[swapThat])
    // But bellow is easier to understand
    let tmpVal = indexList[swapThis]
    indexList[swapThis] = indexList[swapThat]
    indexList[swapThat] = tmpVal
  }
}

создать IBOutlet используйте построитель интерфейса. Используйте Referencing Outlet Collection на каждой ячейке таблицы и перетащите, для каждого, к тому же @IBOutlet в коде контроллера.

enter image description here