Multiple UiCollectionview Reload issue - ios

I have created multiple UICollectionView programmatically and I have set values dynamically working fine. I want update now 3 UICollectionView only. How to reload it.
Below I attached my code:
for (int i=0; i<4; i++) {
CGFloat x =0;
CGFloat viewWidth = CGRectGetWidth(self.view.frame);
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionview =[[UICollectionView alloc] initWithFrame:CGRectMake(0,0, viewWidth, 160) collectionViewLayout:layout];
collectionview.backgroundColor=[UIColor clearColor];
collectionview.tag=i;
[collectionview setTag:i];
[collectionview registerNib:[UINib nibWithNibName:#“Cell” bundle:nil] forCellWithReuseIdentifier:#“Cell”];
collectionview.delegate=self;
collectionview.dataSource=self;
[self.view addSubview:collectionview];
x=x+viewWidth;
}

Get collectionView using viewWithTag.
UICollectionView *Collection = (UICollectionView *)[self.view viewWithTag:3];
Then, just reload the data or do whatever:
[Collection reloadData];

Related

Create Multi UICollectionView in a ViewController

Title is my problem.
I had created UICollectionView in for loop. So, it's created some UICollectionView
My code:
for (int i = 0; i < getAllCategory.count; i ++) {
CGRect frame;
frame.origin.x = self.scroll.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scroll.frame.size;
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
}
So, When I scroll to new UICollectionView to show new image, it's not show new image. Because, it's reload data for last UICollectionView.
My code when show new image.
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
[collectionView reloadData];
}
}
}
So, it's only show old image for all UICollectionView, it's only change image for last UICollectionView
How to I can resolve this problem.
Here is link to you see some images my problem
http://imgur.com/a/nIMic
Please help me!
************************** I had resolved my problem *******************
Add code
#property (strong, nonatomic) NSMutableArray *collectionArray;
self.collectionArray = [[NSMutableArray alloc]init];
[self.collectionArray addObject:collectionView];
[self.collectionArray[page] reloadData];
Your code just handles a collectionView (the last collection).
You should create a property to hold these collectionView: NSMutableArray * arrCollectionView
for (int i = 0; i < getAllCategory.count; i ++) {
CGRect frame;
frame.origin.x = self.scroll.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scroll.frame.size;
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
UICollectionView * collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
[arrCollectionView addObject: collectionView];
}
Then in scrollViewDidScroll
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
//[collectionView reloadData];
for (UICollectionView * collectionView in arrCollectionView) {
if (collectionView == sender) {
[collectionView reloadData];
break;
}
}
}
}
}
Please thinking your design model, you can separate the UICollectionView in different Class, every pointer to object by self, create different array and datasource for load.

IOS UICollectionView with ScrollView

I have 6 images in my database.
I have created UIScrollView *scroll;, after that, I had created UICollectionView and added UICollectionView to UIScrollView
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
And now, when scroll I want reload data of UICollectionView on below this code:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 3) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
[collectionView reloadData];
}
}
}
first pageControl is 2 images.
When I scroll to second pageControl is 2 images(But, it's don't load new image).
When I scroll to third pageControl is 2 images(it's load new image).
You can see some images in my project on below link:
http://imgur.com/a/nIMic
And my project demo.
https://github.com/VMTrinh/Sticker
Please help me!
I guess your problem is that you don't need to embed collection view in a scroll view.
The scroll mechanism is managed by the collection view.
You can scroll your collection with the scrollToItemAtIndexPath: method.

Fill UICollectionViewCells in UICollectionView with data from an array programmatically

I have a UICollectionView which I would like to populate it with 100 UICollectionViewCells each with its own unique UILabel with text fetched from an array. I'd like to do this programmatically (without the Storyboard).
I've attempted it as posted below, but for some reason only the first cell renders properly.
// Setting up the UICollectionView
- (void)setupCollectionView {
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
CGRect newFrame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height * 0.5);
self.collectionView=[[UICollectionView alloc] initWithFrame:newFrame collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[self.collectionView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:self.collectionView];
}
//Trying to generate the unique cells with data
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
cell.backgroundColor = [UIColor yellowColor];
UILabel *label = [[UILabel alloc] initWithFrame: cell.frame];
label.text = [self.array objectAtIndex: indexPath.row];
label.textColor = [UIColor blackColor];
[cell.contentView addSubview:label];
return cell;
}
To note: my array is of size 100 with randomly generated numbers.
Your help is appreciated :)
Thanks!
The array's frame should be related to the bounds of its cell, not its cell's frame, who's origin will grow as the indexPath grows. Also, we don't want to unconditionally create the labels, since the cells get reused. Only create a label if one doesn't exist....
UILabel *label = (UILabel *)[cell viewWithTag:99];
if (!label) {
label = [[UILabel alloc] initWithFrame: cell.bounds]; // note use bounds here - which we want to be zero based since we're in the coordinate system of the cell
label.tag = 99;
label.text = [self.array objectAtIndex: indexPath.row];
label.textColor = [UIColor blackColor];
[cell.contentView addSubview:label];
}
// unconditionally setup its text
NSNumber *number = self.myArrayOfRandomNumbers[indexPath.row];
label.text = [number description];

UICollectionView move specific cell

I have a working sample of UICollectionView, I can move a cell [by indexPath], but I need a specific cell [indexpath.row?] So I move the cell i need, At the moment a cell moves but not the correct one, so
when I move for example
NSIndexPath *index = [indexPaths objectAtIndex:0];
the cell on indexpath.row = 3 moves, how to call the cell by indexpath row?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor lightGrayColor];
CGRect frame = CGRectMake(10, 100, 300, 500);
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
self.collectionView=[[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[self.collectionView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.collectionView];
UIButton *animus = [UIButton buttonWithType:UIButtonTypeRoundedRect];
animus.frame = CGRectMake(100, 20, 90, 30);
[animus setTitle:#"Animus" forState:UIControlStateNormal];
[animus addTarget:self action:#selector(animusPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:animus];
}
- (void)animusPressed:(id)sender
{
NSIndexPath *index = [indexPaths objectAtIndex:0]; //en el index!
NSLog(#"moving tha cell :: %d", index.row);
__weak UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:index]; // Avoid retain cycles
CGRect frame = cell.frame;
frame.origin.y = 300;
cell.frame = frame;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
cell.backgroundColor=[UIColor greenColor];
UILabel *title = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, cell.bounds.size.width, 40)];
[cell.contentView addSubview:title];
NSString *titleLbl = [NSString stringWithFormat:#"i = %d", indexPath.row];
title.text = titleLbl;
return cell;
}
So a cell moves, but not the one I want, I need to move a specific cell, by indexpath.row like it is shown on the cellForRow,
How to specify what cell I want to move?
Please note im moving cell on index = 0 , but the indexpath.row = 2 is the one moving
Thanks
Have you tried something like this?
[NSIndexPath indexPathForItem:0 inSection:0]
First of all, it will be more difficult to make any adjustments your UICollectionView without using an array as your data source. Most commonly, you will have one array holding data and in your cellForItemAtIndexPath: method you grab index-specific data from that array via:
MyData *myData = [self.arrayOfMyData objectAtIndex:indexPath.row];
This way you can populate the cell using data related to the current indexPath. Once you do that, just update your data array and then call:
[self.collectionView reloadData];
Then the updates will be represented in the collection view. If you want to animate those changes, use:
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadData];
} completion:nil];
If you want to "move" cells around with the appearance that it changed its original position, you could manage your arrayOfMyData to add a signifier at the index you want empty to set the background of the cell as clear and put the cell to move at the end of your array, then call reloadData.

UICollectionView shows only the first item

I'm working on a project similar to a video album. In that I'm using UICollectionView to display the thumb images of those videos. The worst part is that I should not use storyboard or xib files. I have tried to do this programatically. I'm currently working on this code:
- (void)viewDidLoad
{
i = 0;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
[layout setItemSize:CGSizeMake(self.view.frame.size.width/2.5,self.view.frame.size.width/2.5)];
collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
collectionView.backgroundColor = [UIColor whiteColor];
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"MyCell"];
[self.view addSubview:collectionView];
[super viewDidLoad];
}
I have given 1 for return in numberOfSectionsInCollectionView and [myArray count] for return in numberOfItemsInSection.
-(UICollectionViewCell *) collectionView:(UICollectionView *)cV cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [cV dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor blackColor];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(cell.frame.origin.x , cell.frame.origin.y, cell.frame.size.width, (cell.frame.size.height - cell.frame.size.height/3))];
cell.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(cell.frame.origin.x , cell.frame.origin.y, cell.frame.size.width, (cell.frame.size.height - cell.frame.size.height/3))];
imageView.image = [UIImage imageNamed:[storeData objectAtIndex:i]];
[cell addSubview:imageView];
i++;
return cell;
}
I have rechecked the images in myArray. When the view loads, the collection view shows only the first image. Other 4 cells are empty. What is wrong with my code?
For those who is experiencing this problem, frame is the key. I've encountered this and changed:
cell.imageView.frame = cell.frame;
into
cell.imageView.frame = cell.bounds;
The op is using:
cell.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(cell.frame.origin.x , cell.frame.origin.y, cell.frame.size.width, (cell.frame.size.height - cell.frame.size.height/3))];
That's why this happened.
You shouldn't be using i as a counter. The whole point of the delegate method sending you an indexPath is that it tells you what information to get from your array of source data. So, remove i and use the indexPath.row instead.
You also don't need 2 image views. But you should probably keep your special subview and not use the cells built in image view.
You do not need a counter. As indicated by Wain, use indexPath.row.
Importantly, you should not create new subviews in cellForItemAtIndexPath, but rather use this method to fill them appropriately with content. You could put the image views into your storyboard prototype cells and identify them with tags. Each cell returned from dequeueReusableCellWithReuseIdentifier will already contain the image view.
you should never create ui elements in cellForRowAtIndexPath:. Subclass a collection view cell like so:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"INIT WITH FRAME FOR CELL");
//we create the UIImageView here
imageView = [[UIImageView alloc] init];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.frame = CGRectMake(cell.frame.origin.x , cell.frame.origin.y, cell.frame.size.width, (cell.frame.size.height - cell.frame.size.height/3));
[self.contentView addSubview:imageView]; //the only place we want to do this addSubview: is here!
}
return self;
}
Then add that subclassed cell as a property and alter this code:]
[collectionView registerClass:[customCellClass class] forCellWithReuseIdentifier:#"MyCell"];
The perform these changes:
-(customCellClass *) collectionView:(UICollectionView *)cV cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = (customCellClass *)[cV dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor blackColor];
imageView.image = [UIImage imageNamed:[storeData objectAtIndex:indexPath.row]];
return cell;
}
A final adjustment would be to move the the [super viewDidLoad] to this:
- (void)viewDidLoad
{
[super viewDidLoad];
//insert the rest of the code here rather than before viewDidLoad
}

Resources