10

I have a doubt: is there any way to intercept a tableView scrolling to add it an action? For example my prototype cell background is red, touching up inside a cell its background color begin blue and scrolling the tableView background color return red. Is it possible to do this?!

Thanks in advance.

Rohit Kumar
  • 868
  • 6
  • 19
Fabio Cenni
  • 801
  • 2
  • 16
  • 27

5 Answers5

43

UITableView inherits from UIScrollView and UITableViewDelegate extends UIScrollViewDelegate.

Particularly you may be interested in scrollViewDidScroll method. So, in your UITableViewDelegate implementation, add the following method:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    NSLog("Table view scroll detected at offset: %f", scrollView.contentOffset.y)
}
redent84
  • 17,763
  • 4
  • 53
  • 83
  • I solve my problem using this two method scrollViewWillBeginDragging for to change cell background color when tableView start scrolling, and scrollViewDidEndDragging for to change color when the tableView stop scrolling. – Fabio Cenni Sep 01 '15 at 22:19
  • 1
    @FabioCelli to detect when the scroll stops, better use `scrollViewDidEndDecelerating`. `scrollViewDidEndDragging` is called when the user finishes dragging the content, but the scroll may still move after that. – redent84 Sep 02 '15 at 08:16
  • Ok I Will use that method! Thanks a lot!! – Fabio Cenni Sep 02 '15 at 09:51
0

In the ViewController that is set as the delegate for the tableView, you can also set the delegate methods of a scrollView. These will be called when the tableView is scrolled as it contains a scrollView.

e.g:

extension ViewController: UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(scrollView: UIScrollView) { 

    }
}
Swinny89
  • 6,860
  • 3
  • 31
  • 52
0

You are better of keeping a variable around e.g. var isBackgroundColorRed: Bool = true

And another for scroll y position when you set the background color to blue. e.g.

var blueBackgroundColorYOffset: CGFloat?

When you set the background color to blue, set the y offset, to the contentView.origin.y.

Then in the delegate for the tableview (which subclasses UIScrollView)

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if !isBackgroundColorRed {
        // apply some color blending between blue and red based on 
        // the amount of movement on y axis, until you reach the limit
        // its also important to take the absolute value of the blueBackgroundColorYOffset
        // and the offset here in scrollViewDidScroll to cover up or down movements
        // say 1 cell's height, then set your isBackgroundColorRed to true
    }
}

Try adding this to your project and update yur bridging header. UIColor-CrossFade

This technique will give you a nice UX rather than a sudden background change.

some_id
  • 28,294
  • 58
  • 173
  • 293
0

CellForRow is a way to detect scrolling which also gives you the indexPath.row of the next cell entering the view. If the user scrolls such a short distance that a new or recycled cell is not even configured, then dragging will not be detected. However even with built in methods, such as scrollViewWillBeginDragging, short distance scrolling will not be detected.

var lastCellForRowAtIndex = 0
var isScrollingUp = false
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    isScrollingUp = indexPath.row > lastCellForRowAtIndex
    lastCellForRowAtIndex = indexPath.row
}
ScottyBlades
  • 7,536
  • 2
  • 50
  • 60
-3

cellForRowAtIndexPath will be repeatedly called when you are scrolling the tableView unless you have very few number of rows.

Rohit Kumar
  • 868
  • 6
  • 19
  • 2
    cellForRowAtIndexPath is ONLY called when the tableview does not have the cell already. It is up to the discretion of the tableView when to hold onto the cells, so there is no guarantee at all that cellForRowAtIndexPath will be called during scrolling. – fishinear Aug 28 '15 at 15:19
  • 1
    I'm very sure of my answer, it will be called either tableView deques the cell or create a new one. You should have tried before downvoting. – Rohit Kumar Aug 28 '15 at 15:22
  • And I have also mentioned when it is not called ie: you have a very few number of rows. – Rohit Kumar Aug 28 '15 at 15:23
  • It is called when a new cell scrolls into view. It is also called initially, and it may be called in other situations when a cell comes into view. That means that there is no guarantee it will be called when scrolling (as you state yourself already). Nor is there a guarantee that when it is called, you are actually scrolling. Therefore, this is not an answer to the OP's question. – fishinear Aug 28 '15 at 15:38
  • 1
    Does matter a new cell or old..just put a log there have 10-20 rows and then scroll...I'll stop answering here if the method doesn't get called. – Rohit Kumar Aug 28 '15 at 15:41
  • 2
    Sigh. Before posting an answer, you should consider whether you are actually answering the OP's question: Can this be used to reliably detect when the tableView is scrolling? The response to that is: NO (as you have admitted yourself already). – fishinear Aug 28 '15 at 15:47
  • Ahh great!! Not here to discuss with you buddy...You should have tried yourself then do the straight answer to YES or NO. - Closed. – Rohit Kumar Aug 28 '15 at 15:50
  • I upvoted your answer Rohit, because sometimes it is more helpful to give the answer to the question you should be asking than the question you are asking. Its kind of nuanced, but cellforrowat actually does give you the information to identify scrolling, but it gives you the actionable information of the indexPath so you can do a wider variety of things than with the current answers. I want to identify when scrolling is happening so that I can fetch data which will be needed in the near future (very fast lazy loading tableView). – ScottyBlades Sep 04 '17 at 05:07
  • @fishinear, cellforrowatindexPath is NOT ONLY called when the tableview does not have the cell already. TableView Cells are recycled, so cellforrowatindexpath is called everytime the tableview needs to add a cell AND when it reconfigures/recycles a cell that is being dequeued. It is basically called when a cell is being introduced to the window. – ScottyBlades Sep 04 '17 at 11:42
  • @fishinear, Rohit didn't admit that cellforrowat isn't a reliable way to detect scrolling, he suggested a very basic test that you can do for yourself to verify that it works. – ScottyBlades Sep 04 '17 at 11:44
  • @ScottyBlades Exacty, cellforrowatindexpath will ONLY be called when the tableview does not have that particular cell already, which is what I already said. In that case, either a new cell will be added or an old one will be recycled. There is still no guarantee that that is needed during scrolling. – fishinear Sep 05 '17 at 20:24
  • @fishinear, Aside from short distance scrolling (which doesn't even call the built in scrolling methods), can you give a use case where cellforrowat isn't called while the user is scrolling? – ScottyBlades Sep 06 '17 at 05:24
  • It’s dependent on the internal implementation of uitableview, which can change with every iOS version, so you cannot rely on it. Right now, when you use different types of cells, one more rare than the other, you can scroll a long distance up and down, without a rare cell that is off-screen being reused. – fishinear Sep 06 '17 at 13:38