0

I have a CollectionView, the cell in CollectionView has size equal to the screen (CollectionView has paging enable mode).

I want to press long on the screen, then the CollectionView will scroll to the next cell.

For example:

I need 1 second to make the CollectionView scroll to the next cell, and I press for 2,5 seconds.

The begining time: I am starting long press on the screen and the collection view is now on the first cell.

After the first second: It will scroll to the second cell.

After the second second: It will scroll to the third cell.

The last half second: It still stand on the third cell (because half second is not enough time to make the collection view scroll to the next cell).

I have added the UILongPressGestureRecognizer to the cell and I have tried like this:

func handleLongPress(longGesture: UILongPressGestureRecognizer) {
        if longGesture.state == .Ended {
            let p = longGesture.locationInView(self.collectionView)
            let indexPath = self.collectionView.indexPathForItemAtPoint(p)

            if let indexPath = indexPath {
                let row = indexPath.row + 1
                let section = indexPath.section
                if row < self.photoData.count {
                self.collectionView.selectItemAtIndexPath(NSIndexPath(forRow: row, inSection: section), animated: true, scrollPosition: .Right)
                }
                print(indexPath.row)
            } else {
                print("Could not find index path")
            }
        }
    }

But I always have to END the long gesture to make the collection view scroll.

halfer
  • 19,824
  • 17
  • 99
  • 186
Twitter khuong291
  • 11,328
  • 15
  • 80
  • 116

2 Answers2

1

What you seem to want is something that kicks off a timer that fires every 1 second while the finger is down. I'd probably make a function:

    func scrollCell() {
        if (longPressActive) {
            //scroll code

            let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))) 
            dispatch_after(dispatchTime, dispatch_get_main_queue(), { 
                scrollCell() // function calls itself after a second 
            })
        }
    }

That you could control in your handleLongPress code:

func handleLongPress(longGesture: UILongPressGestureRecognizer) {
     if longGesture.state == .Began {
         longPressActive = true
         scrollCell()
     } else if longGesture.state == .Ended || longGesture.state == .Canceled {
            longPressActive = false
        }
    }

So, when the long press gesture first fires, it sets a bool (longPressActive), and then calls the scroll function. When the scroll function completes, it calls itself again. If the gesture ever finalizes, it will clear the longPressActive bool, so if the timer fires, the bool will be false and it won't scroll.

More ideally I'd probably not use a long press gesture recognizer and just track the touches myself, as I could reference the touch and check its state instead of use a boolean. Also, there is probably a fun bug involved with the dispatch when it goes into the background.

n_b
  • 1,116
  • 1
  • 11
  • 20
0

Here is the way I have tried:

First, I add these properties to my Controller:

var counter = 0
var timer = NSTimer()
var currentIndexPath: NSIndexPath?

Then I count up the counter whenever longGesture.state == .Began

func handleLongPress(longGesture: UILongPressGestureRecognizer) {
    if longGesture.state == .Began {
        let point = longGesture.locationInView(self.collectionView)
        currentIndexPath = self.collectionView.indexPathForItemAtPoint(point)

        self.counter = 0
        self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(ODIProfileAlbumMode4TableViewCell.incrementCounter), userInfo: nil, repeats: true)
    } else if longGesture.state == .Ended {
        self.timer.invalidate()
    }
}

func incrementCounter() {
    self.counter += 1
    print(self.counter)
    if let indexPath = currentIndexPath {
        let section = indexPath.section
        if self.counter < self.photoData.count {
            self.collectionView.scrollToItemAtIndexPath(NSIndexPath(forRow: self.counter, inSection: section), atScrollPosition: .Right, animated: true)
        } else {
            self.counter = 0
            self.collectionView.scrollToItemAtIndexPath(NSIndexPath(forRow: 0, inSection: section), atScrollPosition: .Right, animated: true)
        }
    } else {
        print("Could not find index path")
    }
}

It works perfectly now. :)

Twitter khuong291
  • 11,328
  • 15
  • 80
  • 116