UICollectionViewでインタラクティブなCellの並び替え

 UICollectionViewでインタラクティブなCellの並び替え

UICollectionViewの並び替えのAPIが、実はiOS 9からあったことに最近気づいた話です。
第31回の #potatotips で発表した内容です。

61fe6537eed31e8d1999ce1c1d5bf988?s=128

himaratsu

July 21, 2016
Tweet

Transcript

  1. UICollectionViewͰ ΠϯλϥΫςΟϒͳCellͷฒͼସ͑ Ryosuke Hiramatsu (@himara2) 2016/07/21 potatotips #31

  2. ࣗݾ঺հ ɾฏদ ྄հ (@himara2) ɾϠϑʔגࣜձࣾ ɾmyThings ͱ͍͏ΞϓϦΛͭͬͯ͘·͢

  3. meyasuba.co ɾ໨҆ശ ɾ3ߦ͘Β͍ίʔυΛॻ͘ͱϢʔβʔͱνϟοτͰ͖ ΔαʔϏε ɾϑΟʔυόοΫ͓Ͷ͕͍͠·͢

  4. UICollectionViewͰ ΠϯλϥΫςΟϒͳCellͷฒͼସ͑

  5. UICollectionView ɾiOS 6͔Β࢖͑ΔϑϨʔϜϫʔΫ ɾෳ਺σόΠεͰͷϨΠΞ΢τʹॊೈ ɾiOS 10Ͱ৭ʑͱڧԽ͞Εͨ

  6. WWDC 2016 “What’s New in UICollectionView in iOS 10”

  7. Interactive Reordering ɾUICollectionViewCell ͷฒͼସ͑ ɾͨͩͷฒͼସ͑Ͱ͸ͳ͘”ΠϯλϥΫςΟϒ”

  8. Interactive Reordering ɾUICollectionViewCell ͷฒͼସ͑ ɾͨͩͷฒͼସ͑Ͱ͸ͳ͘”ΠϯλϥΫςΟϒ” ɾiOS 9͔Βఏڙʢ஌Βͳ͔ͬͨʣ

  9. DEMO

  10. ɾҟͳΔαΠζͰ΋OK ɾΠϯλϥΫςΟϒ ɾϖʔδϯά΋༗ޮ

  11. UICollectionView.h // Support for reordering @available(iOS 9.0, *) public func

    beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool // returns NO if reordering was prevented from beginning - otherwise YES @available(iOS 9.0, *) public func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint) @available(iOS 9.0, *) public func endInteractiveMovement() @available(iOS 9.0, *) public func cancelInteractiveMovement() ࣮૷͢Δ
  12. ࣮૷ํ๏ 1. UIGestureRecognizer Λઃఆ 2. ҠಈͰ͖ΔcellΛࢦఆ͢Δ 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯreorder ͷϝιουΛݺͿ 4.

    σʔλͷೖΕସ͑ͷॲཧΛߦ͏
  13. 1. UIGestureRecognizer Λઃఆ ࠓճ͸௕ԡ͠Ͱฒͼସ͑։࢝͢ΔͨΊ UILongPressGesture Λ࢖ͬͨ let longPressGesture = UILongPressGestureRecognizer(target:

    self, action: #selector(longPressed)) addGestureRecognizer(longPressGesture) PhotoCell.swift
  14. 2. ҠಈͰ͖ΔCellΛࢦఆ @objc(collectionView:canMoveItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath)

    -> Bool { return true } ViewController.swift
  15. 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 1 PhotoCell.swift func longPressed(gestureRecognizer: UILongPressGestureRecognizer) {

    let position = gestureRecognizer.location(in: self) let convertedPosition = convert(position, to: collectionView) switch gestureRecognizer.state { case .began: delegate?.didStartLongPress(position: convertedPosition) case .changed: delegate?.didChangeLongPress(position: convertedPosition) case .ended: delegate?.didEndLongPress(position: convertedPosition) case .cancelled, .failed: delegate?.didCancelLongPress(position: convertedPosition) case .possible: break // do nothing } }
  16. 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 1 PhotoCell.swift func longPressed(gestureRecognizer: UILongPressGestureRecognizer) {

    let position = gestureRecognizer.location(in: self) let convertedPosition = convert(position, to: collectionView) switch gestureRecognizer.state { case .began: delegate?.didStartLongPress(position: convertedPosition) case .changed: delegate?.didChangeLongPress(position: convertedPosition) case .ended: delegate?.didEndLongPress(position: convertedPosition) case .cancelled, .failed: delegate?.didCancelLongPress(position: convertedPosition) case .possible: break // do nothing } }
  17. 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 1 PhotoCell.swift func longPressed(gestureRecognizer: UILongPressGestureRecognizer) {

    let position = gestureRecognizer.location(in: self) let convertedPosition = convert(position, to: collectionView) switch gestureRecognizer.state { case .began: delegate?.didStartLongPress(position: convertedPosition) case .changed: delegate?.didChangeLongPress(position: convertedPosition) case .ended: delegate?.didEndLongPress(position: convertedPosition) case .cancelled, .failed: delegate?.didCancelLongPress(position: convertedPosition) case .possible: break // do nothing } }
  18. 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 2 func didStartLongPress(position: CGPoint) { if

    let indexPath = collectionView.indexPathForItem(at: position) { let success = collectionView.beginInteractiveMovementForItem(at: indexPath) // true } } func didChangeLongPress(position: CGPoint) { collectionView.updateInteractiveMovementTargetPosition(position) } ViewController.swift
  19. 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 2 func didStartLongPress(position: CGPoint) { if

    let indexPath = collectionView.indexPathForItem(at: position) { let success = collectionView.beginInteractiveMovementForItem(at: indexPath) // true } } func didChangeLongPress(position: CGPoint) { collectionView.updateInteractiveMovementTargetPosition(position) } ViewController.swift
  20. 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 2 func didStartLongPress(position: CGPoint) { if

    let indexPath = collectionView.indexPathForItem(at: position) { let success = collectionView.beginInteractiveMovementForItem(at: indexPath) // true } } func didChangeLongPress(position: CGPoint) { collectionView.updateInteractiveMovementTargetPosition(position) } ViewController.swift
  21. ViewController.swift 3. GestureRecognizerͷΠϕϯτʹ͋Θͤͯ reorderΛݺͿ - 3 func didCancelLongPress(position: CGPoint) {

    collectionView.endInteractiveMovement() } func didEndLongPress(position: CGPoint) { collectionView.endInteractiveMovement() }
  22. 4. σʔλೖΕସ͑ͷॲཧ func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to

    destinationIndexPath: IndexPath) { let targetPhoto = photos[sourceIndexPath.row] photos.remove(at: sourceIndexPath.row) photos.insert(targetPhoto, at: destinationIndexPath.row) } ViewController.swift
  23. Complete!

  24. ·ͱΊ 1. UICollectionView΋ฒͼସ͑Ͱ͖Δ 2. UILongPressGestureͳͲͱ͋Θͤͯ࢖͏ 3. ؆୯ʹiPhoneͷϗʔϜը໘ͷΑ͏ͳڍಈ͕࣮૷Ͱ͖Δ

  25. Sample Code https://github.com/himaratsu/ CollectionViewInteractiveSortSample

  26. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

  27. None