In my main view controller, I have a UICollectionView (created by using the IB). And:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
NSLog(#"Cell clicked....%d",[indexPath row]);
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
ChildView *calendar = [[ChildView alloc] initWithDate:newDate];
calendar.delegate = self;
[cell.contentView addSubview:calendar];
return cell;
}
If I touch outside the bounds of the child view, I get the event. If I touch inside the cell, where the child view is, no event is trapped in didSelectCellAtRowIndex.
Why?
The collection view handles its touches internally, so any touch handlers or gesture recognizers on your views will take precedence.
Related
I have a UIViewController with a UICollectionView on it but Xcode doesn't seem to look like every tutorial I find on the Internet or on YouTube - When I drag a UICollectionViewCell to place in the UICollectionView, it won't let me place it.
Now I'm confused as to how I can link my cell to the UICollectionView.
This is the viewController.h file:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [self.imagesArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
ImageViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"imageCell" forIndexPath:indexPath];
NSString *myImageString = [self.imagesArray objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:myImageString];
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake(100.0, 100.0);
}
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(5, 5, 5, 5);
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
//[self.collectionView registerClass:[ImageViewCell class] forCellWithReuseIdentifier:#"imageCell"];
self.imagesArray = #[#"shirt1.PNG", #"pants.png", #"pants2.png"];
}
I'm not using a Storyboard interface but individual xib's. When I run this all that appears is the blank black screen. What am I missing?
-registerNib:forCellWithReuseIdentifier:
If you have your cell defined in a NIB, then you register that NIB with the collection view. That is how the collection view know what to load when -dequeueReusableCellWithReuseIdentifier:forIndexPath: is called.
- (void)viewDidLoad
{
// …
UINib nib = [UINib nibWithNibName:#"<the name of your xib>" bundle:nil];
[self.collectionView registerNib:nib forCellWithReuseIdentifier:#"imageCell"];
// …
}
Because you didn't have new a object of UICollectionViewCell in this method:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
The "cell" in your method must be set to nil.
The settings for the UICollectionView were defined using IB (ie scroll direction: horizontal, etc), and was embedded in UITableViewCell using IB.
UICollectionViewCell displays, images display, however, images are stacked on top of one another, instead of one image per one cell with fidelity.
I made individual UIImageView for each picture as instance variables, and same occurred using if and switch statements in the cellForItemAtIndexPath message.
Since IB was used, it may be a stretch to identify the bug, however, would you please help to identify the bug in case it is obvious from the code? Thanks.
#implementation AccountTableViewCell
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
imageArray = #[[UIImage imageNamed:#"image1.png"], [UIImage imageNamed:#"image2.png"], [UIImage imageNamed:#"image3.png"], [UIImage imageNamed:#"image4.png"], [UIImage imageNamed:#"image5.png"]];
self.oCollectionView.dataSource = self;
[self.oCollectionView setFrame:self.contentView.frame];
[self.contentView addSubview:self.oCollectionView];
self.oCollectionView.backgroundColor = [UIColor clearColor];
[self.oCollectionView reloadData];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return imageArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"accountCell" forIndexPath:indexPath];
UIImageView* iv = [[UIImageView alloc] init];
[cell.contentView addSubview:iv];
[iv setFrame:cell.contentView.frame];
iv.image = imageArray[indexPath.row];
return cell;
}
#end
It's because you keep on adding an UIImageView to the cell each time it's dequeued.
Instead, you should subclass the UICollectionViewCell (let's call it "MYCollectionViewCell", add a UIImageView to the cell subclass in the storyboard and set the UIImageView as an outlet on the subclass.
Then, within cellForItemAtIndexPath, set that imageView's image like so:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"accountCell" forIndexPath:indexPath];
cell.imageView.image = imageArray[indexPath.row];
return cell;
}
since I couldn't use any framework to create an photo album, I'm trying to create my own using Collection View, but I got stuck right at the beginning.
My goal is to display all images from my web service into my collection view, since all displayed, the next step is when someone taps on any cell, I can open it in a new view and also navigate between all.
here is the basic code that I created:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[collectionController reloadData];
tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:nil action:#selector(touched)];
tapGesture.numberOfTapsRequired = 1;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 6;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Cell";
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.imgCollection setImageWithURL:[NSURL URLWithString:#"http://sallescds.com.br/wp-content/uploads/2012/12/xepop-300x300.jpg"] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
[cell.imgCollection addGestureRecognizer:tapGesture];
return cell;
}
-(void)touched:(UIGestureRecognizer *)tap{
NSLog(#"the touch happened");
}
thanks guys.
A couple of things are not right in your code:
First, initWithTarget:action: should not be passed a nil value for target. From the docs :
target
An object that is the recipient of action messages sent by the receiver when it recognizes a gesture. nil is not a valid value.
In your case you should pass self as a target because you want to sent the message touched: to the current instance of your class.
Second, the selector you passed to initWithTarget:action: is wrong. You used #selector(touched) but your method implementation is - (void)touched:(UIGestureRecognizer *)tap;, which selector is #selector(touched:) (mind the :).
I'd recommend reading this question on selectors if your are confused.
Third, you cannot attach a single UIGestureRecognizer to multiple view (see this SO question).
So to make it work, you could create one UITapGestureRecognizer per collection cell (maybe in a subclass). Or better yet, implement your UICollectionViewDelegate method collectionView:didSelectItemAtIndexPath:.
EDIT - How to implement collectionView:didSelectItemAtIndexPath::
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Bind the collectionView's delegate to your view controller
// This could also be set without code, in your storyboard
self.collectionView.delegate = self;
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 6;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.imgCollection setImageWithURL:[NSURL URLWithString:#"http://sallescds.com.br/wp-content/uploads/2012/12/xepop-300x300.jpg"] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
return cell;
}
// I implemented didSelectItemAtIndexPath:, but you could use willSelectItemAtIndexPath: depending on what you intend to do. See the docs of these two methods for the differences.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// If you need to use the touched cell, you can retrieve it like so
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
NSLog(#"touched cell %# at indexPath %#", cell, indexPath);
}
I'm just starting to use the UICollectionView so bear with me!
How do I load a nib into the cell?
It seems I have to register the nib and class to be used, but this does not work.
Code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView registerClass:[CluelessSymbolCell class] forCellWithReuseIdentifier:#"Symbol cell"];
[collectionView registerNib:[UINib nibWithNibName:#"CluelessSymbolCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:#"Symbol cell"];
CluelessSymbolCell *cell = (CluelessSymbolCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"Symbol cell" forIndexPath:indexPath];
CluelessClue *clue = [clueManager clueForIndexPath:indexPath];
[cell.backgroundImageView setImage:[UIImage imageNamed:[clue.imageNames objectAtIndex:0]]];
return cell;
}
It turns out my nib file had the default view controller in it (which was hidden) as well as my custom cell - doh!
I implemented a Collection View programatically in a ViewController and I connected it with the Storyboard but the scrolling is not working and half of the cells do not appear since they are faded to the right:
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[FotoCell class]
forCellWithReuseIdentifier:#"cell"];
UICollectionViewFlowLayout *myLayout = [[[UICollectionViewFlowLayout alloc]init]autorelease];
[myLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.collectionView setCollectionViewLayout:myLayout];
}
Do you know why?
You need to remove the registerClass line in viewDidLoad and set the reuse identifier in the Datasource method for UICollectionViewDelegate as follows -
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath: (NSIndexPath *)indexPath
{
FotoCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
....
return cell;
}