Rectangle 27 0

ios UICollectionView dynamic data source items adding to the beginning of the collection view?


UICollectionView
calendarView
calendarView.showsHorizontalScrollIndicator = false
calendarView.showsVerticalScrollIndicator = false
func scrollViewDidScroll(scrollView_:UIScrollView) {  
    if !enableScrollingHandling {return}
    var currentOffsetX:CGFloat = scrollView_.contentOffset.x  
    var currentOffSetY:CGFloat = scrollView_.contentOffset.y  
    var contentHeight:CGFloat = scrollView_.contentSize.height  
    var offset:CGFloat  

    /*  0.125 - 1/8,  0.5 - 1/2  */
    if currentOffSetY < (contentHeight * 0.125)  {
        enableScrollingHandling = false  
        offset = (contentHeight * 0.125) - currentOffSetY    

        // @todo: your code, specify which days are listed in the first row (2nd screen)

        scrollView_.contentOffset = CGPoint(x: currentOffsetX, y: currentOffset + 
        contentHeight * 0.5 + offset - CGFloat(kRowHeight))

        enableScrollingHandling = true
        return
    }  

    /*  0.75 - 6/8,  0.5 - 1/2  */
    if currentOffSetY > (contentHeight * 0.75)  {  
        enableScrollingHandling = false  
        offset = currentOffSetY - (contentHeight * 0.75)    

        // @todo: your code, specify which days are listed in the first row (1st screen)

        scrollView_.contentOffset = CGPoint(x: currentOffsetX, y: currentOffset - 
        contentHeight * 0.5 - offset + CGFloat(kRowHeight))
        enableScrollingHandling = true
        return
    }  
}
viewDidLoad

Here is the code (translated from Objective-C right here, not tried in the real project):

The important thing is that total amount of rows must be a multiple of 8.

But such an approach to simulate infinitive scrolling with "two screens loop and jumps in between" works really like a charm, very smooth scrolling like behaviour tested on older phones also.

I wrote you in the chat, I made a prototype, you might be interested.

Important notice, I skipped this from original code, but see this is important. When you manually set the contentOffset you also triggers the scrollViewDidScroll event, to prevent this you need to temporary disable your scrollViewDidScroll event processing. You can do it by adding, for example, state variable enableScrollHandling and change its state true/false, see updated code.

In my case it was not a Calendar View but Day View, hours 00:00 - 24:00 listed from top to bottom, so I had UITableView and not UICollectionView but it's not that important in this case.

Instead of manipulation with the data source I created UITableView with the fixed amount of rows, in my case to store exactly two days (48 rows, two days of 24 hours each). You could choose the amount of rows containing in two full screens.

PS: kRowHeight is just a constant the height of the exact row (cell) it's needed for precise and smooth scrolling behaviour it could be skipped I think.

That's actually the very interesting topic. I'll try to explain the idea I came up with while working on another Calendar app.

The idea is that UICollectionView is in fact UIScrollView so when we scroll down or up we can handle the corresponding event and calculate the visible offsets.

The language used was not Swift but Objective-C, so I just try to translate code samples.

Then in your collectionView:cellForItemAtIndexPath: based on what's in the first row (is this content of the first screen or second screen) and what are the current visible days (formula) you just update the cell content.

Then you need a formula to calculate what's the day number for each particular cell based on what's inside the first visible row.

This formula could also be a tricky part and may require some workaround especially if you decide to put Month Names in between months. I do also have some ideas on how to organise it, so if you encounter any problem we can discuss it here.

To simulate the infinitive scrolling we handle the scrollViewDidScroll and check if you just passed the 1/8 of the UIScrollView height scrolling up, move your UIScrollView to the 1/2 of height plus the exact offset so it moves to the "second screen" smoothly. And back, if you passed the 6/8 of the UIScrollView height while scrolling down, move the UIScrollView up to 1/2 of its height minus offset.

wow, great answer, I'll prototype it right now, and then write what I get and about the formula, didn't know about such approach:) Thanks for such great post!

Note