LoginSignup
0
0

More than 3 years have passed since last update.

LongPress GestureでUITableViewのsectionの間にCellを移動する実践

Posted at

ネットでLongPressでUITableViewのCellを移動する文章がありますが、Sectionの間に移動する例はなかなか無いです。今日はその経験を共有しましょう。

実現する方法

1.長押した時、押した場所によって、該当Cellを取得し、IndexPathを変数originIndexPathに渡す。そして、綺麗な動き見えるためにスナップショットを作成して該当Cellを見えないように設定。
2.指が押しながら移動する時、スナップショットの座標Y軸を更新し、新しい位置のCellのIndexPathが元のIndexPathと違うとoriginIndexPathを更新し、データも更新。
3.リリースした時、該当Cellを見えるように設定して、スナップショットを削除。
重要ポイント:
移動の処理について、セクションが変わる場合、もしセクションの一番下から入る時、そのままIndexPathを変数originIndexPathに渡す前に、IndexPathに1行を追加することが必要。

画面操作

Main.storyboardの画面で、LibrayからLong Press Gesture Reconigerをドラグして、UITableVIewのCellの上に置きます。

コード

UITableViewController
import UIKit
import CoreData

class CatalogViewController: UITableViewController{
    //CellのIndexPathを臨時保存用変数
    var originIndexPath: IndexPath?
  //スナップショットの変数
    var initialSnapshot: UIView?
    //長押しジェスチャーの処理
    @IBAction func LongPress(_ sender: UILongPressGestureRecognizer) {
     //ジェスチャーの状態を取得
        let state = sender.state
     //指の位置を取得
        let location = sender.location(in: tableView)
     //指所在のCellのIndexPathを取得
        guard let indexPath = self.tableView.indexPathForRow(at: location) else { return }
        switch state {
       //最初押した時の処理
            case .began:
                    originIndexPath = indexPath
                    guard let cell = self.tableView.cellForRow(at: indexPath) else { return }
                    initialSnapshot = cellSnapshot(inputView: cell)
                    guard let snapshot = initialSnapshot else { return }
                    var center = cell.center
                    snapshot.center = center
                    snapshot.alpha = 0.0
                    self.tableView.addSubview(snapshot)
                    UIView.animate(withDuration: 0.25, animations: {
                        center.y = location.y
                        snapshot.center = center
                        snapshot.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
                        snapshot.alpha = 0.98
                        cell.alpha = 0.0
                    }, completion:{(finished) in cell.isHidden = true })
       //指が移動する時の処理
            case .changed:
                guard let snapshot = initialSnapshot else { return }
                var center = snapshot.center
                center.y = location.y

                snapshot.center = center
                guard let sourceIndexPath = originIndexPath else { return }
                if indexPath.section != sourceIndexPath.section {
                   //IndexPathの更新   
            if indexPath.row + 1 == tableView.numberOfRows(inSection: indexPath.section){
                        originIndexPath = IndexPath(row: indexPath.row + 1, section: indexPath.section)
                        }else{ originIndexPath = indexPath }
           //データの更新、自身のプロジェクトによって修正が必要になります。
                  let cataitem = fetchedResultsController.object(at: sourceIndexPath )
                    cataitem.category = NSNumber(value: indexPath.section).boolValue
                        saveContext()
                }
          //IndexPathの更新
                else if indexPath.row != sourceIndexPath.row {
                    tableView.moveRow(at: sourceIndexPath, to: indexPath)
                    originIndexPath = indexPath
                }
       //指が離れた時の処理
            default:
                guard let cell = self.tableView.cellForRow(at: originIndexPath!) else {return}
                guard let snapshot = initialSnapshot else {return}
                cell.isHidden = false
                cell.alpha = 0.0
                UIView.animate(withDuration: 0.25, animations: {
                    snapshot.center = cell.center
                    snapshot.transform = CGAffineTransform.identity
                    snapshot.alpha = 0
                    cell.alpha = 1
                }, completion: { (finished) -> Void in
                    if finished {
                        self.originIndexPath = nil
                        snapshot.removeFromSuperview()
                        self.initialSnapshot = nil
                    }})
        }
    }
    //スナップショットの作成関数
    private func cellSnapshot(inputView: UIView) -> UIView? {
        UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0)
        if let CurrentContext = UIGraphicsGetCurrentContext() {
            inputView.layer.render(in: CurrentContext)
        }
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
            UIGraphicsEndImageContext()
            return nil
        }
        UIGraphicsEndImageContext()
        let snapshot = UIImageView(image: image)
        snapshot.layer.masksToBounds = false
        snapshot.layer.cornerRadius = 0
        snapshot.layer.shadowOffset = CGSize(width: -5, height: 0)
        snapshot.layer.shadowRadius = 5
        snapshot.layer.shadowOpacity = 0.4
        return snapshot
    }

以上です、Have fun!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0