I am trying to create a CollectionView header having horizontal header section but the problem is the section that is being created is vertical and I want everything to be dynamic.
And for this purpose i am using viewForSupplementaryElementOfKind :-
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableview = nil;
if (kind == UICollectionElementKindSectionHeader) {
DepartmentCollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"HeaderView" forIndexPath:indexPath];
//UILabel *label = [[UILabel alloc] init];
//label.tag = indexPath.row;
headerView.officeName.text=[NSString stringWithFormat:#"%#",_officelist[indexPath.row]];
[self.roadmapCollectionView addSubview:headerView.officeName];
reusableview = headerView;
}
return reusableview;
}
This is working fine(here we are creating labels and buttons in collection view header according to the figure) :-
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"HeaderView" forIndexPath:indexPath];
CGFloat x=0,y=0;
for (int i = 0;i<[_officelist count];i++)
{
id val=[officeSize objectAtIndex:i];
CGFloat val1=[val floatValue];
UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, 10,val1-1,35)];
newLabel.text=[NSString stringWithFormat:#"%#",_officelist[i]];
newLabel.textAlignment = NSTextAlignmentCenter;
newLabel.backgroundColor = [UIColor greenColor];
[self.roadmapCollectionView addSubview:newLabel];
x=x+val1+1;
}
for (int i=0; i<_departmentlist.count; i++) {
dept=[_departmentlist objectAtIndex:i];
id val=[officeSize objectAtIndex:i];
CGFloat val1=[val floatValue];
float val2=val1/[dept count];
//NSLog(#"DEPT SIZE - %f",val2);
for (int j = 0; j < [dept count]; j++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(y, 50,val2-1, 25);
[button setBackgroundColor:[UIColor yellowColor]];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setTitle:[NSString stringWithFormat:#"%#",dept[j]] forState:UIControlStateNormal];
[self.roadmapCollectionView addSubview:button];
[deptSize addObject:[NSNumber numberWithFloat:y]];
y=y+val2+1;
}
}
return reusableView;
}
Could you please try the below code (using DateFlowLayout)
bool isPortrait = UIInterfaceOrientationIsPortrait(orientation);
self.collectionView.frame = isPortrait ? CGRectMake(0, 0, 768, 180) : CGRectMake(0, 60, 246, 595);
self.collectionView.collectionViewLayout = isPortrait ? DateFlowLayout.new : UICollectionViewFlowLayout.new;
self.flowLayout = ((UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout);
self.flowLayout.scrollDirection = isPortrait ? UICollectionViewScrollDirectionHorizontal : UICollectionViewScrollDirectionVertical;
self.flowLayout.headerReferenceSize = isPortrait ? CGSizeMake(5, 30) : CGSizeMake(246, 40); //width is margin to the left of the header - must be bigger than 0 to show headers correct.
self.flowLayout.minimumInteritemSpacing = isPortrait ? 10 : 0;
self.flowLayout.minimumLineSpacing = isPortrait ? 17 : 7;
self.flowLayout.sectionInset = isPortrait ? UIEdgeInsetsMake(27, 30, 25, 0) : UIEdgeInsetsMake(0, 14, 0, 0);
//self.flowLayout.itemSize = CGSizeMake(58, 85); //You might need this
self.collectionView.alwaysBounceVertical = isPortrait ? NO : YES;
Related
How to Create multiple column in an one row.
Like this image!. https://pbs.twimg.com/media/CEuO0hUUUAARX_L.png !
You can also use gridview for your requirement like GMGridView or UIGridView
Check below sample code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* cellIdentifier = #"gridCell";
UITableViewCell *gridCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(gridCell == nil)
{
gridCell = [[[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:cellIdentifier] autorelease];
gridCell.accessoryType = UITableViewCellAccessoryNone;
gridCell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSArray* items = [_grids objectAtIndex:indexPath.section];
int imageIndex = 0;
int yOffset = 0;
while (imageIndex < items.count)
{
int yPos = 4 + yOffset * 74;
for(int i = 0; i < 4; ++i)
{
CGRect rect = CGRectMake((18 + i * 80), yPos, 40, 40);
UIImageView* imageView = [self gridImageRect:rect forImage:[items objectAtIndex:imageIndex]];
[gridCell.contentView addSubview:imageView];
[imageView release];
rect = CGRectMake(((80 * i)-4), (yPos+44), 80, 12);
UILabel* label = [self descriptionOfImage:imageIndex inRect:rect];
[gridCell.contentView addSubview:label];
[label release];
++imageIndex;
}
++yOffset;
}
return gridCell;
}
I've got this problem with a UICollectionView inside a UICollectionViewCell:
The last UICollectionViewCell doesn't get filled with 13 - 18, but instead, the first one get's copied.
I know it has something to do with "dequeueReusableCellWithReuseIdentifier" but if I don't do the check on the tag below, my entire collection gets messed up.
I've been struggling with this issue and Googling around for about a day now, but I can't find how to fix this.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellID=#"pageCell";
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
int no = indexPath.item;
if(collectionView == _pageCollectionView)
{
//Collection pages
cell.tag=no+1;
UICollectionViewFlowLayout *layoutMods=[[UICollectionViewFlowLayout alloc] init];
[layoutMods setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[layoutMods setMinimumInteritemSpacing:0];
[layoutMods setMinimumLineSpacing:0];
[layoutMods setItemSize:CGSizeMake(125, 125)];
_modsCollectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(0,0, _pageCollectionView.frame.size.width, _pageCollectionView.frame.size.height) collectionViewLayout:layoutMods];
[_modsCollectionView setDataSource:self];
[_modsCollectionView setDelegate:self];
_modsCollectionView.pagingEnabled = YES;
[_modsCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"pageCell"];
NSMutableArray *randColor = [[NSMutableArray alloc] init];
for(int i=0;i<3;i++)
{
int lowerBound = 0;
int upperBound = 255;
NSNumber *rndValue = [NSNumber numberWithFloat:(lowerBound + arc4random() % (upperBound - lowerBound) )/255.0];
[randColor insertObject:rndValue atIndex:i];
}
float r = [[randColor objectAtIndex:0] floatValue];
float g = [[randColor objectAtIndex:1] floatValue];
float b = [[randColor objectAtIndex:2] floatValue];
_modsCollectionView.backgroundColor = [UIColor colorWithRed:r green:g blue:b alpha:1];
[cell addSubview:_modsCollectionView];
}
else
{
if(cell.tag == 0)
{
cell.tag = 2;
NSMutableDictionary *mod=[modules objectAtIndex:modulePointer];
cell.backgroundColor=[mod objectForKey:#"color"];
NSString *slug = [mod objectForKey:#"slug"];
NSString *imgName=[NSString stringWithFormat:slug,#".png"];
UIImageView *customBackground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imgName]];
customBackground.frame = CGRectMake(0,0, 125, 125);
[cell addSubview:customBackground];
customBackground.contentMode = UIViewContentModeScaleAspectFit;
customBackground.clipsToBounds = YES;
modulePointer++;
}
}
return cell;
}
What am I doing wrong?
Got it! I had to work some magic using view tags inside - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath.
In the if(collectionView == _pageCollectionView) i put:
for(id subview in [cell subviews])
{
[subview removeFromSuperview];
}
cell.tag=itemsPerScreen*no;
And then in the following else:
int thisIndex=[collectionView superview].tag+no;
NSMutableDictionary *mod=[modules objectAtIndex:thisIndex];
You need to create your own custom UICollectionViewCell to prevent this from happening.
I have double items in my collectionView. How can I fix it?
I have UITableViewCell with UICollectionViewCell inside it.
I set elements size and direction based on its count.
My cell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.layout = [[UICollectionViewFlowLayout alloc] init];
self.layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
self.layout.itemSize = CGSizeMake(70, 70);
self.layout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.collectionView = [[IndexedCollectionView alloc] initWithFrame:CGRectMake(10, 250, 60, 320) collectionViewLayout:self.layout];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:CollectionViewCellIdentifier];
self.collectionView.backgroundColor = [UIColor whiteColor];
self.collectionView.showsHorizontalScrollIndicator = NO;
[self.contentView addSubview:self.collectionView];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)layoutSubviews
{
[super layoutSubviews];
self.collectionView.frame = self.contentView.bounds;
}
-(void)setCollectionViewDataSourceDelegate:(id<UICollectionViewDataSource, UICollectionViewDelegate>)dataSourceDelegate index:(NSInteger)index
{
self.collectionView.dataSource = dataSourceDelegate;
self.collectionView.delegate = dataSourceDelegate;
self.collectionView.index = index;
[self.collectionView reloadData];
}
Delegate Methods
-(FeedCell *)collectionView:(IndexedCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
FeedCell *cell = (FeedCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CollectionViewCellIdentifier forIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc]init];
imageView.frame = collectionView.frame;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES;
NSInteger count = [self test:collectionView].count;
if (count == 0)
{
return nil;
}
NSInteger imageIndex = 0;
if (count == 1)
{
[imageView setFrame:CGRectMake(0, 110, 310, 200)];
imageIndex = indexPath.item;
imageView.contentMode = UIViewContentModeScaleAspectFit;
}
if (count == 2)
{
[imageView setFrame:CGRectMake(0, 110, 150, 200)];
imageIndex = indexPath.item;
imageView.contentMode = UIViewContentModeScaleAspectFit;
}
if (count == 3)
{
[imageView setFrame:CGRectMake(10, 100, 90, 90)];
imageIndex = indexPath.item;
}
if (count == 4)
{
[imageView setFrame:CGRectMake(10, 100, 130, 130)];//2lines
imageIndex = indexPath.item;
}
if (count == 5 || count == 6)
{
[imageView setFrame:CGRectMake(10, 100, 90, 90)];//2lines
imageIndex = indexPath.item;
}
if (count > 6)
{
[imageView setFrame:CGRectMake(10, 100, 100, 100)];//2lines
imageIndex = indexPath.item ;
//cell.layout.itemSize = CGSizeMake(50, 50);
}
imageView.image = [DataManager imageFromPath:[self test:collectionView][imageIndex]];
[cell.contentView addSubview:imageView];
return cell;
}
The way you create the collectionView Cell in the table view Cell is not correct. Here are some references you can refer to create a collection view.
Collection View Cell Apple Reference.
Create Collection View without Storyboard
Refer to my answer here. You need to subclass your cells.
What is happening is you are dequeuing an existing cell, and then adding in another subview over it. Most of the users on here argue that the ONLY way to fix this is to go through the main subclassing method. It is faster and more "formal", however, you can add another tool to your toolbox:
Instead, you can test if the subview has already been added WITHOUT subclassing, and just stick it in a logic block. Here is what you can do:
BOOL doesContain = [cell.subviews containsObject:imageView];
if (!doesContain)
{
[cell.contentView addSubview:imageView];
}
imageView.image = [DataManager imageFromPath:[self test:collectionView][imageIndex]];
I am trying to create something like this here.
Here is the sample code which I tried:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"RefundMeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
cell.selectionStyle=UITableViewCellSelectionStyleNone;
}
UIImageView *rowImageView=(UIImageView*)[cell viewWithTag:1];
UILabel *questionOptionLabel=(UILabel*)[cell viewWithTag:2];
UIImageView *collapseImageView=(UIImageView*)[cell viewWithTag:3];
UIScrollView *scrollView=(UIScrollView*)[cell viewWithTag:4];
UIImageView *sampleImageView=(UIImageView*)[cell viewWithTag:5];
UIButton *sampleButton=(UIButton*)[cell viewWithTag:6];
UILabel *instructionHeaderLabel=(UILabel*)[cell viewWithTag:7];
UILabel *instructionsLabel=(UILabel*)[cell viewWithTag:8];
UIPageControl *pgCntrl=(UIPageControl*)[cell viewWithTag:9];
[rowImageView setImage:[UIImage imageNamed:#"normalcell.png"]];
questionOptionLabel.text = #"";
collapseImageView.image = nil;
scrollView.hidden = YES;
sampleImageView.image = nil;sampleImageView.hidden = YES;
sampleButton.hidden = YES;
instructionHeaderLabel.text = #"";instructionHeaderLabel.hidden = YES;
instructionsLabel.text = #"";instructionsLabel.hidden = YES;
pgCntrl.hidden = YES;
[sampleButton addTarget:self action:#selector(userImageButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
sampleImageView.image = nil;
[collapseImageView setImage:[UIImage imageNamed:#"down.png"]];
questionOptionLabel.text=#"";
instructionHeaderLabel.text=#"Instructions";
if (indexPath.row == 0)
{
instructionHeaderLabel.hidden = NO;
sampleImageView.image = self.barcodeImage;
scrollView.hidden = NO;
scrollView.delegate = self;
pgCntrl.hidden = NO;
sampleImageView.hidden = NO;
sampleButton.hidden = NO;
pgCntrl.numberOfPages = 5;
pgCntrl.currentPage = 0;
for (int i = 0; i<5; i++)
{
[scrollView addSubview:sampleImageView];
[scrollView addSubview:sampleButton];
}
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 5, scrollView.frame.size.height);
}
else
{
instructionHeaderLabel.hidden = NO;
sampleImageView.image = nil;
scrollView.hidden = NO;
scrollView.delegate = self;
pgCntrl.hidden = NO;
sampleImageView.hidden = NO;
sampleButton.hidden = NO;
pgCntrl.numberOfPages = 3;
pgCntrl.currentPage = 0;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 3, scrollView.frame.size.height);
}
return cell;
}
My problem is, how I can add UIImageView, UILabel, etc when UIScrollView is scrolled to second page?
It should look like this
Currently UIImageView, UILabel is shown only first time. when I scroll to second page, UIImageView and UILabel scroll back and nothing is shown on second page.
Here is my code
- (void)viewDidLoad
{
[super viewDidLoad];
tableObj.dataSource = self;
tableObj.delegate = self;
scrollView.delegate = self;
// customObj = [[customCellForText alloc]init];
imageArray = [[NSMutableArray alloc]initWithObjects:[UIImage imageNamed:#"image1.jpg"],
[UIImage imageNamed:#"image2.jpg"],
[UIImage imageNamed:#"man-actor-Ashton-Kutcher-Wallpaper.jpg"],
[UIImage imageNamed:#"Man-Booker-Prize-judges-p-011.jpg"],
[UIImage imageNamed:#"man-curl.jpg"]
,nil];
// pageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(170, 180, 100, 30)];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"cell";
customCellForText *cell = [tableObj dequeueReusableCellWithIdentifier:cellIdentifier];
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:#"customCellForText" owner:self options:nil];
cell = [nib objectAtIndex:0];
scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(130, 80, 150, 100)];
scrollView.pagingEnabled = YES;
scrollView.delegate = self;
[scrollView setShowsHorizontalScrollIndicator:NO];
//[scrollView setShowsVerticalScrollIndicator:NO];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * imageArray.count, self.scrollView.frame.size.height);
[cell.contentView addSubview:scrollView];
for (int i = 0; i < imageArray.count; i++){
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
subview = [[UIImageView alloc] initWithFrame:frame];
subview.image = [imageArray objectAtIndex:i];
subview.contentMode = UIViewContentModeScaleAspectFit;
[self.scrollView addSubview:subview];
}
pageControl = [[UIPageControl alloc]init];
pageControl.frame = CGRectMake(170, 180, 100, 30);
pageControl.numberOfPages = imageArray.count;
pageControl.currentPage = 0;
pageControl.hidesForSinglePage = YES;
[cell.contentView addSubview:pageControl];
[pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
cell.nameLabel.text=#"amol";
return cell;
}
- (void)scrollViewDidScroll:(UIScrollView *)sender{
CGFloat pageWidth = sender.frame.size.width;
int newPage = floor((sender.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = newPage;
}
I would recommend you to use a different approach because your solution is not scalable. If you want n pages you'll have to add n images & label to your scroll view which will be a mess and also not memory efficient.
Give a look at this library I think it will suit your need.
I have created a collectionview that has different data in each column. But to seperate them I need to add header . I can add only one header. My code for this is:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableview = nil;
UILabel *lblHeader;
if (kind == UICollectionElementKindSectionHeader) {
RePrecioHeader *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"CollectionHeaderView" forIndexPath:indexPath];
NSArray *cellsInSection = self.ClassesArr[indexPath.section];
float collectionWidth = self.view.bounds.size.width;
int cellsInSectionCount = cellsInSection.count;
float cellWidth = (collectionWidth) / cellsInSectionCount;
cellWidth -= 10* (cellsInSectionCount -1);
for(int i=0;i<self.ClassesArr.count; i++){
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(85/self.ClassesArr.count,-5, cellWidth, 40)];
view.backgroundColor = [UIColor grayColor];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 14)];
lbl.textColor = [UIColor whiteColor];
lbl.font = [UIFont systemFontOfSize:12.0f];
lbl.backgroundColor = [UIColor clearColor];
lbl.text = [[[self.ClassesArr objectAtIndex:i]objectAtIndex:0]objectForKey:#"textoClase"];
[view addSubview:lbl];
[self.collectionView addSubview:view];
}
reusableview = headerView;
}
return reusableview;
}
The column number should be like the number of ClassesArr..
I have fixed my problem. Thanks.
RePrecioHeader *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"CollectionHeaderView" forIndexPath:indexPath];
UILabel *lblHeader=(UILabel *)[headerView viewWithTag:MY_HEADER_LABEL_TAG];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(5,0, 80, 30)];
view.backgroundColor = [UIColor grayColor];
lblHeader = [[UILabel alloc] initWithFrame:CGRectMake(2,3, 60, 10)];
lblHeader.backgroundColor = [UIColor clearColor];
lblHeader.textColor=[UIColor whiteColor];
lblHeader.font = [UIFont systemFontOfSize:11.0f];
lblHeader.numberOfLines=2;
lblHeader.textAlignment=NSTextAlignmentCenter;
lblHeader.text =[[[self.ClassesArr objectAtIndex:indexPath.section]objectAtIndex:0]objectForKey:#"textoClase"];
[view addSubview:lblHeader];
[headerView addSubview:view];