Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 712
user3369214 Avatar asked Aug 07 '15 14:08

user3369214


2 Answers

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)
like image 57
ielyamani Avatar answered Nov 15 '22 17:11

ielyamani


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.

like image 26
hasan Avatar answered Nov 15 '22 17:11

hasan