user3369214
user3369214

Reputation: 431

UICollectionView inside UIView container: didSelectRowAtIndexPath doesn't get called after scroll

I have 3 UIViews Header / Tabar / Container embedded un a ScrollView in a ViewController. So this is my structure :

enter image description here

In the ContainerView I load a UICollectionView (like this) :

let controller = storyboard!.instantiateViewControllerWithIdentifier("myCollectionViewController") as! myCollectionViewController
controller.delegate = self

self.addChildViewController(controller)
controller.view.backgroundColor = UIColor.brownColor()
self.containerView.addSubview(controller.view)
controller.didMoveToParentViewController(self)

Everything works perfectly, each cells of the UICollectionView are loaded,... The only problem is that, all the hidden cells (and even all the parts of cells that are hidden) are not selectable. What I mean is my function "didSelectRowAtIndexPath" doesn't work for every pixel out of the first screen. This is a scheme of my problem :

This is what I have before the scroll (on the left is a scheme, on the right is what I actually have on the screen) -> here everything works fine :

enter image description here

This is what I have after the scroll (on the left is a scheme, on the right is what I actually have on the screen) -> only the pixels that were displayed before the scroll can call "didSelectRowAtIndexPath" :

enter image description here

The problem reside in the fact self.view.frame is not refreshing well. Do you have an idea of how I should change this frame and when?

Upvotes: 9

Views: 4189

Answers (3)

Swapnil Luktuke
Swapnil Luktuke

Reputation: 10475

This seems like the continuation of another problem you have mentioned in another question.

Looking at the storyboard hierarchy, i suspect the problem is, you are not changing the height of your tab bar view when you are changing scroll view content size and the collection view height. Collection view is still visible, probably because your container tab bar view does not clip contents (clipToBounds=false). But since the view itself does not extend that far below, touches are not recognised by the view and it's subviews.

Make sure you main view, scroll view's content view (content size), tab bar view AND collection view are all resized correctly. Since you have decided not to go with standard view hierarchy (supplementary view or header view), you have to handle the overhead of managing the view bounds yourself.

Upvotes: 0

hasan
hasan

Reputation: 24195

Problem Definition:

All the time we face a situation were our UIViewController, in addition to the scroller view, displays headers and tab bars. The problem is that those additional views reduces the area associated to our scroller (in this case UICollectionView). In small screen devices our scroller will display a small number of items at a time.

Proposed Solution:

Let those additional views scrolls along with the scroller items.

How to Apply it?!

The most convenient solution to achieve that. Appears in the Scroller View itself. The UICollectionView for example, provides Supplementary Elements (Headers and Footers) which scrolls with the collection view items. Move your header and tabbar to the header area of the UICollectionView. then, implement the viewForSupplementaryElementOfKind in your view controller:

- (nonnull UICollectionReusableView *)collectionView:(nonnull UICollectionView *)collectionView viewForSupplementaryElementOfKind:(nonnull NSString *)kind atIndexPath:(nonnull NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"Header1" forIndexPath:indexPath];

    return reusableview;
}

Interface Builder: The header area for the UICollectionView already exists. But, you need to set the height for it via the interface builder in-order to appear in design time. Do not forget to set the Collection Reusable View Identifier for the header.

enter image description here

Note: This also requires you some extra work in order to set the gestures on your header and TabBar.

Update:

Consider to remove the header and tabbar container and re-add it as a subview in it's proper place at runtime. when the UICollectionView tab get clicked pass it to the header reusable view in the viewForSupplementaryElementOfKind method. when a tab of labels get clicked add it on top of the labels container view. and when it's a tableview pass it to the UITableView header in the headerForRow method.

Upvotes: 1

ielyamani
ielyamani

Reputation: 18591

You have to define the scroll view content size

Create an outlet to your scrollview

@IBOutlet weak var scrollview : UIScrollView!

Make its height equal the sum of the heights of the header, the tabBar and the container:

self.scrollView.contentSize = CGSizeMake(self.view.frame.width, header.frame.height + tabBar.frame.height + container.frame.height)

Upvotes: 2

Related Questions