I am trying to use RFQuiltLayout in my Collection View and I keep running into an size/margin issue. It seems appears fine using the 4s and 5s simulator but when I test it on the 6 or 6plus, the blocks get pushed over to the left side of the screen and leave a large margin on the right.
Not sure what's going on here.
image of problem
storyboard
Here is the code for the collection view controller
.h
#import "RFQuiltLayout.h"
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UICollectionViewDataSource, UICollectionViewDelegate, RFQuiltLayoutDelegate, UICollectionViewDelegateFlowLayout>
#property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
#property (nonatomic, strong) NSArray *greekLetters;
.m
#import "ViewController.h"
#import "CollectionViewCell.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
RFQuiltLayout* layout = (id)[self.collectionView collectionViewLayout];
layout.direction = UICollectionViewScrollDirectionVertical;
layout.blockPixels = CGSizeMake(75, 75);
self.greekLetters = #[#"Alpha", #"Beta", #"Cappa",#"Delta", #"Epsilon", #"Zeta", #"Eta", #"Theta", #"Iota", #"Kappa", #"Lambda", #"Mu", #"Nu", #"Xi", #"omicron", #"pi",#"rho",#"sigma", #"tau", #"upsilon", #"phi", #"chi",#"psi",#"omega"];
// [[self collectionView]setDataSource:self];
// [[self collectionView]setDelegate:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma - mark CollectionView DelegateMethods:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return self.greekLetters.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifer = #"cell";
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifer forIndexPath:indexPath];
cell.cellLabel.text = [self.greekLetters objectAtIndex:indexPath.row];
return cell;
}
#pragma mark – RFQuiltLayoutDelegate
-(CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout blockSizeForItemAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row %2) {
return CGSizeMake(2, 3);
}else{
return CGSizeMake(2, 2);
}
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetsForItemAtIndexPath:(NSIndexPath *)indexPath {
return UIEdgeInsetsMake(5, 5, 5, 5);
}
#end
Not sure what could be causing it.
Any help is greatly appreciated.
thanks.
just play with the blockpixels
for mine these values work perfectly
layout.blockPixels = CGSizeMake(106.66, 106.66);
Related
I'm trying to have a UICollectionViewController inside my UIViewController.
Here's how I set it up
TagsCollectionViewController* tagsCollectionViewController = [[TagsCollectionViewController alloc] initWithCollectionViewLayout:[UICollectionViewLayout new]];
UIView *tagsView = tagsCollectionViewController.view;
[self.view addSubview:tagsView]; // setting up constraings too
And this is my TagsCollectionViewController
#interface TagsCollectionViewController () <UICollectionViewDelegateFlowLayout>
#end
#implementation TagsCollectionViewController
static NSString * const reuseIdentifier = #"Cell";
- (void)viewDidLoad {
[super viewDidLoad];
self.collectionView.backgroundColor = [UIColor yellowColor];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 20;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}
#pragma mark <UICollectionViewDelegateFlowLayout>
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(50, 50);
}
#end
What's strange is that I get yellow view so my collection seems to be working, however I don't get to see any items. But when I present whole controller everything works fine. So the problem occurs only when I'm trying to embed it. What can be the issue?
EDIT: Related: Adding UICollectionViewController to UIViewController Not Working
It looks as if it's a problem with estimating the size of items in the collection. I was able to get results by using the following code after creating a similar example and noticing that cells weren't being requested.
#interface ViewController ()
#property (nonatomic, strong) TagsCollectionViewController *tags;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
layout.itemSize = CGSizeMake(50.0, 50.0);
self.tags = [[TagsCollectionViewController alloc] initWithCollectionViewLayout:layout];
UIView *tagsView = self.tags.view;
[self.view addSubview:tagsView];
}
Hi there i have a slight problem with my UICollectionView. i don't currently have any settings set for spacing yet i seem to have a huge gap between my cells of which is very annoying if would be helpful if someone could tell me how to resolve this? id assume its something very simple.
Below is an example of whats happening to my CollectionViewCells:
Custom cell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *IconImage;
#property (weak, nonatomic) IBOutlet UILabel *IconLabel;
#property (weak, nonatomic) IBOutlet UILabel *IconDescription;
#end
groupsviewcontroller.m
#import "GroupsViewController.h"
#import "CustomCell.h"
#interface GroupsViewController ()
{
NSArray *arrayOfImages;
NSArray *arrayOfDescriptions;
}
#end
#implementation GroupsViewController
{
NSString *reuseIdentifier;
}
- (void)viewDidLoad
{
[super viewDidLoad];
reuseIdentifier= #"SmallIcon";
[[self GroupsCollectionView]setDataSource:self];
[[self GroupsCollectionView]setDelegate:self];
arrayOfImages = [[NSArray alloc]initWithObjects:#"sin.png", nil];
arrayOfDescriptions = [[NSArray alloc]initWithObjects:#"Sin", nil];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [arrayOfDescriptions count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[[cell IconImage]setImage:[UIImage imageNamed:[arrayOfImages objectAtIndex:indexPath.item]]];
[[cell IconLabel]setText:[arrayOfDescriptions objectAtIndex:indexPath.item]];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//Dispose of any resources that can be recreated.
}
- (IBAction)cellToggleAction:(id)sender {
//need to add toggle button to toggle between three different views
//small icon
//list view
//large icon
}
#end
1) You should check your CustomCell class, see if any size constraint is applied. Simply set your cell's background as some color and the actual cell size will be highlighted.
2) Use (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath to help yourself set the proper cell size. This func comes with UICollectionViewDelegateFlowLayout :)
i have created some code in my button to toggle between my cell identifier of which does so pretty well but obviously i needed to set and initial cell identifier of which is small icon, so how would i go about remove that cell identifier and replacing it with another once the button is clicked. My current code is as follows:
GroupsViewController.m
#import "GroupsViewController.h"
#import "CustomCell.h"
#interface GroupsViewController ()
{
NSArray *arrayOfImages;
NSArray *arrayOfDescriptions;
}
#end
#implementation GroupsViewController
{
NSString *reuseIdentifier;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[self GroupsCollectionView]setDataSource:self];
[[self GroupsCollectionView]setDelegate:self];
reuseIdentifier= #"SmallIcon";
arrayOfImages = [[NSArray alloc]initWithObjects:#"?.png", nil];
arrayOfDescriptions = [[NSArray alloc]initWithObjects:#"?", nil];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [arrayOfDescriptions count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[[cell IconImage]setImage:[UIImage imageNamed:[arrayOfImages objectAtIndex:indexPath.item]]];
[[cell IconLabel]setText:[arrayOfDescriptions objectAtIndex:indexPath.item]];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//Dispose of any resources that can be recreated.
}
- (IBAction)cellToggleAction:(id)sender {
if([reuseIdentifier isEqualToString:#"SmallIcon"])
reuseIdentifier=#"ListView";
else if
([reuseIdentifier isEqualToString:#"ListView"])
reuseIdentifier=#"LargeIcon";
else if
([reuseIdentifier isEqualToString:#"LargeIcon"])
reuseIdentifier=#"SmallIcon";
[self.GroupsCollectionView reloadData];
}
#end
CustomCell.h
#import <UIKit/UIKit.h>
#interface CustomCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *IconImage;
#property (weak, nonatomic) IBOutlet UILabel *IconLabel;
#end
I assume its to do with me setting the reuseIdentifier in the
- (void)viewDidLoad so that i didn't get any errors so that i hadn't set one, so really what i am asking for is a way to set the initial reuseidzntifier and replace it will the following when i toggle between the button clicks.
Also it would be helpful if someone could point me in the right direction as to adding icon images to each click of the button.
The problem happens when i am clicking the button as shown in the following images, the cells themselves change but the initial cell identifier stays put.
From what I understand your UICollectionViewCells are working fine. You just need to adjust their size when cells are toggled.
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize cellSize;
// Return required size based on your identifiers
if([reuseIdentifier isEqualToString:#"SmallIcon"])
cellSize = CGSizeMake(50, 50); // Sample size
else if
([reuseIdentifier isEqualToString:#"ListView"])
cellSize = CGSizeMake(80, 80); // Sample size
else if
([reuseIdentifier isEqualToString:#"LargeIcon"])
cellSize = CGSizeMake(120, 120); // Sample size
return cellSize;
}
I have a UICollectionViewController with a custom UICollectionViewCell with an image and a label outlet. The images only fill correctly AFTER I press reload to reload the data. I notice that the labels disappear too, though I feel they
are just behind the images.
What am I doing wrong?
ON LOAD
AFTER RELOADING THE DATA
This is how big the images should be when the view is loaded.
I set the cells to be a factor of how big the screen size is. NSLogging the Frames I can see that the Cell size and the image size are the same.
Cell size: 124.85
PhotoView size: {{0, 0}, {124.85, 124.85}}
CollectionViewController.h
#import <UIKit/UIKit.h>
#import "HomeModel.h"
#interface CollectionViewController : UICollectionViewController <UICollectionViewDelegateFlowLayout>
#end
CollectionViewController.m
#import "CollectionViewController.h"
#import "CollectionViewCell.h"
#define SPACE_BETWEEN_CELLS 0.05
#interface CollectionViewController () {
NSArray * _feedItems;
}
- (IBAction)reloadUserData:(id)sender;
#end
#implementation CollectionViewController
static NSString * const reuseIdentifier = #"Cell";
- (IBAction)reloadUserData:(id)sender {
[self.collectionView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations
self.clearsSelectionOnViewWillAppear = YES;
self.collectionView.allowsMultipleSelection = NO;
_feedItems = [NSArray arrayWithObjects:#"1.jpg", #"2.jpg", #"3.jpg", #"4.jpg", #"5.jpg", nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [_feedItems count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
//IMAGE
cell.photoView.frame = CGRectMake(0, 0, cell.bounds.size.width, cell.bounds.size.height);
cell.photoView.backgroundColor = [UIColor colorWithRed:128 green:128 blue:128 alpha:0.5];
cell.photoView.image = [UIImage imageNamed:[_feedItems objectAtIndex:indexPath.row]];
NSLog(#"PhotoView size: %#", NSStringFromCGRect(cell.photoView.frame) );
return cell;
}
#pragma mark <UICollectionViewDelegateFlowLayout>
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat size = ( [[UIScreen mainScreen] bounds].size.width / 3 ) - ( SPACE_BETWEEN_CELLS * 3);
NSLog(#"Cell size: %f ", size);
return CGSizeMake( size, size);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return SPACE_BETWEEN_CELLS;
}
#end
Here is my custom cell
CollectionViewCell.h
#import <UIKit/UIKit.h>
#interface CollectionViewCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIImageView *photoView;
#property (weak, nonatomic) IBOutlet UILabel *textLabel;
#end
CollectionViewCell.m
#import "CollectionViewCell.h"
#implementation CollectionViewCell
- (void)awakeFromNib {}
#end
Reduce the height of the image view (Photo view),
Do not keep its height same as the height of the cell, otherwise the label will also disappear.
cell.photoView.frame = CGRectMake(0, 0, cell.bounds.size.width, cell.bounds.size.height - 20);
If using auto layout give the image view, constraints from (top, left and right and set its height), and for the label give constraints (bottom and align it horizontally center in the cell).
If using auto resizing then set the following settings,
for image view
and for the label
I have a UICollectionView and I simply want it to show up. I have the delegate and datasource attached to the file's owner in the interface builder.
collectionView:numberOfItemsInSection:
Gets called just fine.
I have been messing with this for a few hours and just can't figure it out...
Any help would be great, Thanks in advance!
Here is the full source. Sorry if its kinda messy.
.h File
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "PinAnnotation.h"
#import "Jot.h"
#interface JotCardViewController : UIViewController <MKMapViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property (nonatomic,strong) Jot* jot;
#end
.m file
#import "JotCardViewController.h"
#import "JotViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface JotCardViewController ()
#property (nonatomic,strong) JotViewController *detailViewController;
#property (nonatomic,strong) IBOutlet UIView *cardFrontView;
#property (nonatomic,assign,getter = isFlipped) BOOL flipped;
#property (nonatomic,weak) IBOutlet MKMapView *mapView;
#property (nonatomic,strong) IBOutlet UICollectionView *collectionView;
#property (nonatomic,weak) IBOutlet UILabel *jotTitle;
#property (nonatomic,weak) IBOutlet UILabel *jotDate;
#property (nonatomic,weak) IBOutlet UILabel *sunriseSunsetDelta;
#property (nonatomic,weak) IBOutlet UILabel *jotNotes;
#end
#implementation JotCardViewController
- (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 from its nib.
[[self mapView] setRegion:MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake([self.jot.latitude floatValue], [self.jot.longitude floatValue]), 1000, 1000)];
//TODO: if there is no jot location - say that their isn't (maybe text over the map display)
CLLocation *tempLocation = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake([self.jot.latitude doubleValue], [self.jot.longitude doubleValue]) altitude:0 horizontalAccuracy:0 verticalAccuracy:0 timestamp:nil];
[self dropPin:tempLocation];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"Cell"];
[self.collectionView reloadData];
}
- (void) viewWillAppear:(BOOL)animated
{
[self refreshUIFromJot];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)flipToDetails:(id)sender
{
if (![self isFlipped]) {
if (!self.detailViewController) {
JotViewController *jotViewController = [[JotViewController alloc] initWithNibName:#"JotView" bundle:[NSBundle mainBundle]];
jotViewController.jot = self.jot;
self.detailViewController = jotViewController;
self.detailViewController.view.frame = self.cardFrontView.frame;
self.detailViewController.view.layer.cornerRadius = 10.0;
}
[UIView transitionFromView:self.cardFrontView toView:self.detailViewController.view duration:0.33 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) {
[self setFlipped:YES];
}];
} else {
[UIView transitionFromView:self.detailViewController.view toView:self.cardFrontView duration:0.33 options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
[self setFlipped:NO];
}];
}
}
- (void) setJot:(Jot *) jot {
_jot = jot;
[self refreshUIFromJot];
}
- (void) refreshUIFromJot
{
[[self jotTitle] setText:self.jot.summary];
[[self jotDate] setText:self.jot.recorddate];
[[self jotNotes] setText:self.jot.note];
[[self sunriseSunsetDelta] setText:#""];
}
-(void) dropPin: (CLLocation*)newLocation{
for (id<MKAnnotation> pin in self.mapView.annotations){
MKAnnotationView* anView = [self.mapView viewForAnnotation: pin];
if (anView){
[self.mapView removeAnnotation:pin];
NSLog(#"Pin removed");
}
}
PinAnnotation *pin = [[PinAnnotation alloc] initWithCoordinates:newLocation.coordinate placeName:nil description:nil];
[self.mapView addAnnotation:pin];
}
#pragma mark - MKMapViewDelegate methods
- (void) mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
NSLog(#"Map!");
}
#pragma mark - UICollectionView DataSource
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section
{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
//cell.backgroundColor = [UIColor colorWithPatternImage:[self.results objectAtIndex:indexPath.row]];
return cell;
//###
/*
NSSet *jotImages = self.jot.images;
NSSortDescriptor *imageNameDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"imageName" ascending:YES];
NSArray *sortedJotImages = [jotImages sortedArrayUsingDescriptors:#[imageNameDescriptor]];
*/
//###
}
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// TODO: Select Item
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
// TODO: Deselect item
}
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize retval = CGSizeMake(100, 100);
return retval;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(50, 20, 50, 20);
}
#end
I was having a similar problem. cellForItemAtIndexPath was not being called. After pulling out my hair for several minutes, I removed the collectionView registerClass:forCellWithReuseIdentifier from the viewDidLoad method.
After doing that, cellForItemAtIndexPath began to get called.
I hope this helps.
I had a similar problem and here was my solution:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
was not being called was because of the itemSize for the collectionViewFlowLayout's height was too big.
[self.myCollectionViewFlowLayout setItemSize:CGSizeMake(320, 548)];
If I change the height to 410, it will execute cellForItemAtIndexPath.
I found I was had a wrong setup custom flow layout class causing me issues. Reverted to Flow layout and it worked fine.