简体   繁体   中英

UICollectionView layout malfunction

I'm building a dictionary app, and one of the features is that you can "drill down" into a definition. You look up a word, there's a word in the definition you don't understand, so you tap that word and the app shows you the definition for that word, if available. This is pretty standard for iOS dictionary apps on the App Store, if anyone's familiar.

One feature is that I am going to have a bar that shows each word as you drill down, so you get a sort of "chain" of words across this horizontal bar. The idea is you can tap on the words in the chain to navigate forwards and backwards through your chain of words.

To represent this chain I am using a UICollectionView, with a subclassed UICollectionViewController. Since it's essentially a "grid" with a single row, this made sense to me. I'm using a storyboard, so I simply embedded my custom controller into the main view, pass events back and forth between the master controller and this custom collection controller. Pretty simple.

Now, let's say the user taps many different words, so you get the "chain" of UICollectionViewCells growing across the bar from left to right until you hit the edge. Since UICollectionView is based on/has a UIScrollView in it, this shouldn't be a problem. My concept is that, if the number of items to be displayed exceeds the width of the view, the CollectionView would expand the contentView and place items off the right edge of the view port, and I could then programmatically scroll the view to show the newly added item.

Here's the code that I use to do this (edited). It's a method that I call in my subclassed UICollectionViewController:

- (void)reloadDataWithAnimation
{
    [self.collectionView performBatchUpdates:^{
        [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
    } completion:^(BOOL finished) {
            [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:model.data.count - 1 inSection:0]
                                        atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
        }

    }];
}

This is more or less what I'd normally do with a UITableView: tell it to reload its data after I have changed the model. It didn't quite work at first until I found a question on SO that covered the use of performBatchUpdates , and I had trouble doing the scrollToItemAtIndexPath until I realized it needed to go into the completion block.

Now, here's the funky part: everything works fine before the items fill up the whole view. The first time an item would go beyond the boundaries, the CollectionView places the item below the last item in the row. This looks really strange because the view is only one row tall, so you can kinda half-see the item parked below the last one in the row, mostly obscured. No scrolling occurs.

At this point, if you scroll the CollectionView back and forth, the item reconfigures itself and moves into the correct position. Or, if you add another item, they align correctly and the view scrolls as intended. Successive additions work just fine. However, if you scroll back to the left and then add another item, it briefly appears underneath the last currently visible item in the viewport, then the view scrolls off to the far right and as it scrolls the misplaced item jumps up into its proper position.

Although I began posting this question as I could find nothing on Stack Overflow, in the course of writing my question, the Similar Question sidebar updated and I found similar questions, and eventually an answer.

Similar question: UICollectionView cell layout is out of the collection view's bounds

Apparently this issue is known to Apple.

Here is the solution linked to in the above question: https://stackoverflow.com/a/13389461/700471

The code that Nick Snyder posted solved the problem for me perfectly.

Edit: Additionally, in the end I subclassed UICollectionViewLayout, bypassing FlowLayout, and made my own layout with this tutorial .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM