はじめに
iOS9以上のみのサポートですが、
CollectionViewCellを簡単に移動できるメソッドがあることを最近知りましたので、
共有します。(遅)
動作イメージ
サンプルコード
まずは、サンプルコードを御覧ください。
CollectionViewの実装自体は、特別なことをしていません。
ロングタップのジェスチャー部分に注目してください。
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
private var numbers = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
numbers = loadTestData()
addEventListner()
}
//ダミーデータです
private func loadTestData() -> [Int]{
for i in 1...100 {
numbers.append(i)
}
return numbers
}
private func addEventListner() {
let longPressGesture = UILongPressGestureRecognizer(target: self,
action: #selector(self.handleLongGesture(_:)))
collectionView.addGestureRecognizer(longPressGesture)
}
//ここがポイントです
func handleLongGesture(gesture: UILongPressGestureRecognizer) {
switch(gesture.state) {
case UIGestureRecognizerState.Began:
guard let selectedIndexPath = collectionView.indexPathForItemAtPoint(gesture.locationInView(collectionView)) else {
break
}
collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
case UIGestureRecognizerState.Changed:
collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
case UIGestureRecognizerState.Ended:
collectionView.endInteractiveMovement()
default:
collectionView.cancelInteractiveMovement()
}
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numbers.count
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(LabelCollectionViewCell.reuseIdentifier,
forIndexPath: indexPath) as! LabelCollectionViewCell
cell.number = numbers[indexPath.item]
return cell
}
func collectionView(collectionView: UICollectionView,
moveItemAtIndexPath sourceIndexPath: NSIndexPath,
toIndexPath destinationIndexPath: NSIndexPath) {
let tempNumber = numbers.removeAtIndex(sourceIndexPath.item)
numbers.insert(tempNumber, atIndex: destinationIndexPath.item)
}
}
UILabelだけのCollectionViewCellです。
LabelCollectionViewCell.swift
import UIKit
protocol ReusableView: class {}
extension ReusableView where Self: UIView {
static var reuseIdentifier: String {
return String(self)
}
}
class LabelCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var numberLabel: UILabel!
var number = 0 {
didSet {
numberLabel.text = "\(number)"
}
}
}
extension LabelCollectionViewCell: ReusableView {}
ちょっと解説
ドラッグ&ドロップの機能は、ロングタップのジェスチャーと連動して、
下記のメソッドを呼ぶだけです。
メソッド名 | 説明 |
---|---|
beginInteractiveMovementForItemAtIndexPath(indexPath: NSIndexPath) | 移動開始 |
updateInteractiveMovementTargetPosition(targetPosition: CGPoint) | 移動中 |
endInteractiveMovement() | 移動終了 |
cancelInteractiveMovement() | 移動の取り消し |
まとめ
iOS10の正式リリース間近ですが、
iOS9でも知らない機能がまだまだあるようです。
iOS8までは、ドラッグ&ドロップの実装は大変でしたが、
iOS9では簡単にできるようになっていたようです。(遅 2回目)
iPhone標準カレンダーのような実装ができるように鍛錬したいと思います。