I try to add a header to each section of the collectionView.
The collectionView without header works fine. When I checkmark the Accessories Section Header in Interfacebilder, the header will be shown in the simulator.
I added a UICollectionViewFlowLayout Class (as File) and called it within the viewDidLoad of my UICollectionView Controller. In the FlowLayout I want to configure the zIndex and Size.
Now the header will not be shown in the simulator, additionaly I added breakpoints in the UICollectionViewFlowLayout but they will never be hit...
How do I get the headers shown in the collectionview, and how do I influence the zIndex and size of the header in the correct way?
SurroundViewController.h
#import <UIKit/UIKit.h>
#interface SurroundViewController : UICollectionViewController
#end
SurroundViewController.m
#import "SurroundViewController.h"
#import "MagazineCell.h"
#import "LazyJoeHeaderLayout.h"
static NSString * const cellID = #"cellID";
#interface SurroundViewController ()
#end
#implementation SurroundViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.collectionView.collectionViewLayout = [[LazyJoeHeaderLayout alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 2;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
mCell.backgroundColor = [UIColor lightGrayColor];
return mCell;
}
#pragma mark Collection view Layout things
// Layout set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Settings Size for Item at index %d", indexPath.row);
CGSize mElementSize = CGSizeMake(104, 104);
return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 2.0;
}
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 2.0;
}
// Layout: Set Edgees of whole screen - not mElementsize
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0);
}
#end
LazyJoeHeaderLayout.h
#import <UIKit/UIKit.h>
#interface LazyJoeHeaderLayout : UICollectionViewFlowLayout
#end
LazyJoeHeaderLayout.m
#import "LazyJoeHeaderLayout.h"
#implementation LazyJoeHeaderLayout
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
attributes.frame = CGRectMake(0, 0, 100, 100);
attributes.zIndex = 1024;
return attributes;
}
#end
MagazineCell.h and MagazineCell.m not listed as not needed for this problem.
Found a solution to show the header, below the updated code to my question, regarding the headersize.
SurroundViewController
#import "SurroundViewController.h"
#import "MagazineCell.h"
#import "LazyJoe.h"
static NSString * const cellID = #"cellID";
#interface SurroundViewController ()
#property (nonatomic, strong) LazyJoe *lazyJoe;
#end
#implementation SurroundViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.lazyJoe = [[LazyJoe alloc]init];
self.collectionView.collectionViewLayout = self.lazyJoe; // Layout things are in the Flowlayout
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 2;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
mCell.backgroundColor = [UIColor lightGrayColor];
return mCell;
}
LazyJoe.m
#import "LazyJoe.h"
#implementation LazyJoe
- (id)init {
if (!(self = [super init])) return nil;
self.itemSize = CGSizeMake(104, 104);
self.sectionInset = UIEdgeInsetsMake(0,0,0,0); // That the items can align as nearest as possible
self.minimumInteritemSpacing = 2.0f; // spacing between items in one row
self.minimumLineSpacing = 2.0f; // spacing between lines
self.headerReferenceSize = CGSizeMake(self.collectionView.frame.size.width, 140);
return self;
}
#end
Related
[update - collection view is nil for some reason...]
None of the collection view delegate methods (cellforitemat, numberofitemsinsection, sizeforitem etc) are being called at all for some reason. I have set the datasource and delegate. I've tried it in interface builder and in code in view did load. Am I missing something??
in the .h:
#interface ViewController : UIViewController<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
#property (nonatomic, strong) NSArray *workoutList;
in the .m (workoutlist.count is 3 on print statement in VDL but not run elsewhere):
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.workoutCV.backgroundColor = [UIColor blackColor];
self.view.backgroundColor = [UIColor blackColor];
self.workoutCV.delegate = self;
self.workoutCV.dataSource = self;
NSLog(#"here %lu", (unsigned long)self.workoutList.count);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
NSLog(#"and here %lu", (unsigned long)self.workoutList.count);
return self.workoutList.count;
}
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString * const cellId = #"HomeCell";
HomeMenuCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(CGRectGetWidth(collectionView.frame), CGRectGetHeight(collectionView.frame) / self.workoutList.count);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
I am segue from a different Viewcontroller (HomeController) to get to this new controller. This is the code from the .m of the HomeController:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
ViewController *nextVC = [[ViewController alloc] init];
nextVC.workoutList = #[#"Squats", #"Stiff Leg DL", #"Abs"];
[self.navigationController pushViewController:nextVC animated:true];
}
It pushes the nextVC fine and print statements run but no cells show up and no print statements run from any of the collection view delegate methods
I don't know what happens, but calling reloadData on the collection view causes nothing. Nothing happens. Maybe I'm missing something, I just don't know what.
I've tried with data on launch and it worked, the collection view was populated. But fetching remote data and then calling reloadData afterwards is not populating the collection view.
Thank you in advance
Class is below:
FoodChannelsCollection.h
#import <UIKit/UIKit.h>
#import "YouTubeDataAPI.h"
#interface FoodChannelsCollection: UIViewController <YouTubeDataAPIDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
#end
FoodChannelsCollection.m
#import "FoodChannelsCollection.h"
#import "ChannelCell.h"
#import "UIImageView+ImageLoader.h"
#interface FoodChannelsCollection()
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#end
#implementation FoodChannelsCollection
//#synthesize collectionView;
NSMutableArray *channels;
//-------------------------------------------------------------------------//
// MARK: Controller's main view setup
//-------------------------------------------------------------------------//
- (void)viewDidLoad
{
[super viewDidLoad];
channels = [NSMutableArray new];
YouTubeDataAPI *dataApi = [YouTubeDataAPI getInstance];
dataApi.delegate = self;
[dataApi fetchFirstChannelsBatch];
}
//-------------------------------------------------------------------------//
// MARK: YouTubeDataAPIDelegate
//-------------------------------------------------------------------------//
- (void)getFirstChannelsBatch:(NSArray *)firstChannelsBatch
{
if (firstChannelsBatch == nil) { return; }
NSLog(#"firstChannelsBatch count: %i", [firstChannelsBatch count]);
if ([firstChannelsBatch count] == 0) { return; }
NSLog(#"firstChannelsBatch count(2): %i", [firstChannelsBatch count]);
[channels addObjectsFromArray: firstChannelsBatch];
NSLog(#"Channels count (Del): %i", [channels count]);
[self.collectionView reloadData];
}
//-------------------------------------------------------------------------//
// MARK: UICollectionViewDelegateFlowLayout
//-------------------------------------------------------------------------//
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
int width = [UIScreen mainScreen].bounds.size.width;
return CGSizeMake(width/2, width/2);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 0;
}
//-------------------------------------------------------------------------//
// MARK: UICollectionViewDataSource
//-------------------------------------------------------------------------//
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSLog(#"Channels count: %i", [channels count]);
return [channels count];
//return 8;
}
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
Channel *channel = channels[indexPath.row];
ChannelCell *cell = (ChannelCell *)[collectionView dequeueReusableCellWithReuseIdentifier: #"ChannelCell" forIndexPath: indexPath];
[cell.thumbnail setImageWithUrl: channel.thumbnailUrl];
[cell.channelTitle setText: channel.channelTitle];
//[cell.channelTitle setText: #"Test Cell"];
return cell;
}
//-------------------------------------------------------------------------//
// MARK: Memory Warning
//-------------------------------------------------------------------------//
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I am new in objective c. I want to create a layout design like android app store. Which means, i have a tableview and each row of tableview has a collectionview, and one more thing, i am using xcode7 and i want to create a design with storyboard. When i should create a that type of design each tableview row show collectionview but my problem is that each collectionview have save data. but i want to different data in every row. I go throw many tutorial but i can't understand. Can anyone assist me, how to create that type of design? Now i am create a tableview datasourse and delegate method in viewcontroller.m file and also use collection view's datasourse and delegate method into custom tableview cells.m class. please any one assist me
each collectionview have save data. but i want to different data in every row
because your collection view's datasourse and delegate method in tableViewCell is same.maybe it's not ok to determine dataSource and delegate implementation in tableViewCell ,you can delegate it out to your ViewController, and each tableViewCell's has different implementation.
I have try to implementation a demo , it can work ,but i think may have better way. this is my code
Cell.h
//Cell.h
#import <UIKit/UIKit.h>
#class MTTableViewCell;
#protocol MTTableViewCellDelegate <NSObject>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section InTableViewCell:(MTTableViewCell *)cell;
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath InTableViewCell:(MTTableViewCell *)cell;
#end
#interface MTTableViewCell : UITableViewCell<UICollectionViewDelegateFlowLayout,UICollectionViewDataSource>
#property (nonatomic, weak) id<MTTableViewCellDelegate> delegate;
#property (nonatomic, strong) UICollectionView *collectionView;
#property (nonatomic, assign) NSInteger index; // [tablview indexPathForCell:] not work before cell is render
#end
Cell.m
//Cell.m
#import "MTTableViewCell.h"
#interface MTTableViewCell()
#end
#implementation MTTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
_collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:layout];
}
return self;
}
#pragma mark -
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (_delegate && [_delegate respondsToSelector:#selector( collectionView:numberOfItemsInSection:InTableViewCell:)]) {
return [_delegate collectionView:collectionView numberOfItemsInSection:section InTableViewCell:self];
}
return 0;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath {
if (_delegate && [_delegate respondsToSelector:#selector( collectionView:cellForItemAtIndexPath:InTableViewCell:)]) {
return [_delegate collectionView:collectionView cellForItemAtIndexPath:indexPath InTableViewCell:self];
}
return nil;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *) collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(50, 50);
}
#end
ViewController.m
#import "ViewController.h"
#import "MTTableViewCell.h"
#interface ViewController ()<UITableViewDataSource,UITableViewDelegate,MTTableViewCellDelegate>
#property (nonatomic, strong) UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.rowHeight = 72.0;
[self.view addSubview:_tableView];
}
#pragma mark - UITableViewDataSource & UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MTTableViewCell *cell = (MTTableViewCell*) [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[MTTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.index = indexPath.row;
cell.delegate = self;
[cell.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"CCell"];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:( NSIndexPath *)indexPath {
MTTableViewCell *mtCell = (MTTableViewCell *)cell;
if (!mtCell.collectionView.superview) {
[mtCell addSubview:mtCell.collectionView];
mtCell.collectionView.delegate = mtCell;
mtCell.collectionView.dataSource = mtCell;
}
}
#pragma mark - MTTableViewCellDelegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath InTableViewCell:(MTTableViewCell *)cell {
UICollectionViewCell *cCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CCell" forIndexPath:indexPath];
cCell.backgroundColor = [UIColor redColor];
return cCell;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section InTableViewCell:(MTTableViewCell *)cell {
[_tableView indexPathForCell:cell];
return cell.index
;
}
#end
Hope this can help you :)
I´m trying to implement a CollectionViewController, where the images sizes are shown correctly. But when I implement the method "collectionViewLayout sizeForItemAtIndexPath", none of the images are shown. Does anybody know why? Here is my CollectionViewController code:
#import "PhotosViewController1.h"
#interface PhotosViewController1 ()
#end
#implementation PhotosViewController1
- (void)viewDidLoad
{
[super viewDidLoad];
_carImages = [#[#"Wild-Love.jpg",
#"d919004663f99c934b20c1bd46fcad3e.jpg",
#"164_v-viergalerie.jpg"] mutableCopy];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark UICollectionViewDataSource
-(NSInteger)numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return _carImages.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotosCell *myCell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"MyCell"
forIndexPath:indexPath];
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:_carImages[row]];
myCell.imageView.image = image;
return myCell;
}
#pragma mark -
#pragma mark UICollectionViewFlowLayoutDelegate
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:_carImages[row]];
return image.size;
}
#end
Can't understand why cellForRowAtIndexPath is never called, even though numberOfRowsInSection is called
I call this ViewController with
ServerDataController *dataController = [[ServerDataController alloc] initWithNibName:#"ServerDataController" bundle:nil];
[self presentModalViewController:dataController animated:YES];
here is my code:
Header file:
#import <UIKit/UIKit.h>
#interface ServerDataController : UIViewController <NSXMLParserDelegate, NSURLConnectionDelegate, UITableViewDataSource>
{
...
NSMutableArray *items;
UITableView *docsTableView;
}
#property (retain, nonatomic) IBOutlet UITableView *docsTableView;
#property (nonatomic, readonly) NSMutableArray *items;
#end
Implementation file:
#import "ServerDataController.h"
#implementation ServerDataController
#synthesize docsTableView;
#synthesize items;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (id)init
{
self = [super init];
if (self)
{
}
return self;
}
- (void)dealloc {
[items release];
[docsTableView release];
[super dealloc];
}
- (void)viewDidAppear:(BOOL)animated
{
[self fetchEntries];
animated = YES;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
if (self) {
items = [[NSMutableArray alloc] init];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self items] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *cellTitle = [[[[items objectAtIndex:indexPath.row] docUrl] lastPathComponent] stringByDeletingPathExtension];
cell.textLabel.text = cellTitle;
return cell;
}
Any suggestions?
I don't see where you add items to your array, only an init in your viewDidLoad, I think it is empty, so that is why the function is never called. There simply aren't any items to be displayed.