I show several cells in a collectionview, some of those cells are paired (stereo audio channels) and i want them to be merged together as seemingly 1 button, rather than having the generic collectionview padding other cells have.
Is there a way I can remove the padding between 2 specific cells to merge into 1 larger cell? Perhaps removing the right hand padding of the first cell in the pair? Or is this beyond the scope of the collectionview?
Here is my delegate method:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CDCBusSelectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
NSString *busNameString = [self.busNamesRecieved objectAtIndex:indexPath.row];
cell.busNameCell.text = busNameString;
NSNumber *busStereoState = [self.busStereoStateRecieved objectAtIndex:indexPath.row];
NSInteger busIntState = [busStereoState integerValue];
if (busIntState == 1) {
// stereo -- need to merge cells or something
[cell setBackgroundColor:[UIColor colorWithRed:255 green:90 blue:127 alpha:1.0]];
}
return cell;
}
Related
I am in the process of creating an App to take care of Maintenance Planning for Harley Davidson enthusiasts.
The planned target is the iPad series at this point.
I wish do display a grid that shows detail for each fuel purchase. The following graphic hopefully shows what I am trying to achieve.
To get this, I’m using the UICollectionView as I don’t think there is another View that gives me what I am after.
The code below illustrates how I have done this – but I believe it’s a pretty chunky way of doing it:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FuelCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor lightTextColor];
cell.cellLabel.text = [NSString stringWithFormat:#" %# %# %# %#",self.fuelDetailsForSelectedBike[indexPath.row][0],self.fuelDetailsForSelectedBike[indexPath.row][1],self.fuelDetailsForSelectedBike[indexPath.row][2],self.fuelDetailsForSelectedBike[indexPath.row][3]];
return cell;
}
What I would prefer is have a cell for each piece of information but unsure how I would achieve this using the UICollectionView.
You already have created a custom cell FuelCollectionViewCell which is a good starting point.
Probably you have a prototype cell in your Storyboard with subclass FuelCollectionViewCell right?
In this cell, add 4 UILabel aligned in one row as your design and 'link' them to your subclass .h file with a simple drag+alt (as you've done with cellLabel).
And update your cellForItemAtIndexPath method with something like:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FuelCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor lightTextColor];
cell.dateLabel.text = self.fuelDetailsForSelectedBike[indexPath.row][0];
cell.litresLabel.text = self.fuelDetailsForSelectedBike[indexPath.row][1];
cell.distanceLabel.text = self.fuelDetailsForSelectedBike[indexPath.row][2];
cell.costLabel.text = self.fuelDetailsForSelectedBike[indexPath.row][3];
return cell;
}
I have a problem i create UICollectionView with custom cell to display items. But after refresh of the UICollectionView reusable cell populate for wrong index
UICollectionView before refresh.
UICollectionView after refresh.
Code example of the reusable collection view cell.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GalleryCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (indexPath.item != 0)
{
[cell setCollectionItem:[collectionData_ objectAtIndex:indexPath.row - 1]];
}
return cell;
}
Think it's reusing another cell (the balloon in this case) and is not setting anything for the first index cell. If you make an else statement to create a new camera cell, hopefully it will reappear.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GalleryCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (indexPath.item != 0) {
[cell setCollectionItem:[collectionData_ objectAtIndex:indexPath.row - 1]];
} else {
// Set camera item here
}
return cell;
}
This problem occurs because the cells will be reused. Cells are reused to improve the performance of the system. If your table has 1000 cells, the system does not allocate 1000 cells but a much lower then reuse-
Try with adding else clause to the if
if (indexPath.item != 0)
{
[cell setCollectionItem:[collectionData_ objectAtIndex:indexPath.row - 1]];
}
else
{
//Set your cell at index 0 with your camera image
[cell setCollectionItem:#"camera-image"];
}
I have to implement a chess style grid view to show some radial progress bar.!
I made the grid using some inefficient algorithm to do this, since UiCollectionView don't use rows and columns, and it worked, but when the user scrolled the collection to the limit and the "row" of the collection disappear from the screen and the user release the screen and the UICollectionViewCells reappear they switched its colors.
I know the switching happens by the BOOLs, but i don't know how solve this.
This is my algorithm (i have 2 differents UICollectionViewCells, one for each color)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
static NSString *identifierPair = #"CellPair";
UICollectionViewCell *cell ;
UILabel *title;
//...Creating the circle progress bar....
if ((indexPath.item % 2) == 0) {
if (isPair) {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifierPair forIndexPath:indexPath];
isPair = NO;
title = (UILabel *)[cell viewWithTag:12];
}
else
{
cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
isPair = YES;
title = (UILabel *)[cell viewWithTag:11];
}
}
else {
if (isUneven) {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifierPair forIndexPath:indexPath];
isUneven = NO;
title = (UILabel *)[cell viewWithTag:12];
}
else
{
cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
isUneven = YES;
title = (UILabel *)[cell viewWithTag:11];
}
}
//...Setting the name to the cell....
return cell;
}
This seems more the case of using a single checkered background inside the UICollectionView, but since I'm not sure that it is doable you could do something like:
+ (BOOL)checkersCellAtIndexIsDark:(NSIndexPath *)indexPath {
NSInteger squareIndex = indexPath.item % 4;
return (squareIndex == 0 || squareIndex == 3);
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = ([[self class] checkersCellAtIndexIsDark:indexPath])? [UIColor orangeColor] : [UIColor yellowColor];
// Set other things
return cell;
}
I don't understand why you use different reuseIdentifiers and titleLabels for different backgrounds since I don't notice from the screens, but you can always edit this code
You didn't have to use 2 different cells to change the background.
All you need is to set the default color of the background and when the indexPath.item is even, just set the other color for the cell background.
But is important to set the default color first, otherwise you will have the same result.
Following code is a very simple program which is used to display numbers from 1-10000 in the UICollectionView. It is displaying correctly without scrolling, but the cells are overlapped if you scroll down and scroll back the collection view.
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 10000;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake(100,30);
}
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *identifier = #"cell_id";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
[label setText:[NSString stringWithFormat:#"%d", indexPath.item, nil]];
[cell.contentView addSubview:label];
return cell;
}
The problem here is that the label is being added to the view's cell repeatedly. The old label is not removed when the cell is reused and hence you see multiple numbers overlapped. the solution can be to remove the old label like this
for (UIView *view in cell.contentView.subviews) {
if ([view isKindOfClass:[UILabel class]]) {
[view removeFromSuperview];
}
}
before adding to the cell. However this will create performance problems when the number of subviews increase. You can create a custom cell with a label and then update its value. I haven't tried it but i believe it will work. Hope this helps
This worked for me in Swift 3:
Almost same solution as approved solution, note that I used
cell.subViews
instead of
cell.contentView.subViews
What's worked for me is:
for view in cell.subviews {
view.removeFromSuperview()
}
Set the cell layer anchorPointZ to row index in cellForItemAtIndexPath: method
cell.layer.anchorPointZ = CGFloat(indexPath.row)
I am using collectionView in my App. I am setting image for the cell backgroundView in didSelect delegate. But When i select one cell indexPath the image is getting set for 3 cell indexPath. When i scroll the collectionView the images are getting changed randomly? Please Help me. thanks in advance.
- (void)viewDidLoad
{
[super viewDidLoad];
[collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:uio];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section
{
return 50;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collection dequeueReusableCellWithReuseIdentifier:uio
forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"index %#",indexPath);
UICollectionViewCell *cell = [collection cellForItemAtIndexPath:indexPath];
cell.backgroundView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"download.jpg"]];
}
That's because you reuse your cell. An option would be to have an dictionary variable to say that your cell has been selected and reset the image if it has not been.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"index %#",indexPath);
UICollectionViewCell *cell = [collection cellForItemAtIndexPath:indexPath];
cell.backgroundView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"download.jpg"]];
[selectedDictionary setObject:[NSNumber numberWithBool:YES] forKey:[NSNumber numberWithInteger:indexPath.row]];
}
Then in your cellForItemAtIndexPath method you would check that value
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collection dequeueReusableCellWithReuseIdentifier:uio
forIndexPath:indexPath];
BOOL selected = [[selectedDictionary objectForKey:[NSNumber numberWithInteger:indexPath.row]] boolValue];
if(selected){
cell.backgroundView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"download.jpg"]];
}else{
cell.backgroundView = nil;
}
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
Of course if you use some kind of object as model, it would appropriate to have a selected variable in here, you won't need a nsdictionary any more.
The Problem is dequeueReusableCellWithReuseIdentifier.
When you scroll UICollectionview then cell are reused that is problem
add Collectionview inside scrollview.
Try this Inside:
Scroll_View is Your Scroll View
collection is Your Collectionview
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
self.Scroll_View.contentSize = CGSizeMake(self.view.frame.size.width, collectionView.contentSize.height);
CGRect fram_For_Collection_View = self.collection_view.frame;
fram_For_Collection_View.size.height = collectionView.contentSize.height;
self.collection.view.frame = fram_For_Collection_View;
}
Your -collectionView:didSelectItemAtPath: is adding a new image view to the cell. Nothing is removing that image view when the cell is reused. So, when you say:
UICollectionViewCell *cell = [collection dequeueReusableCellWithReuseIdentifier:uio
forIndexPath:indexPath];
in your -collectionView:cellForItemAtIndexPath:, you're may get back some cell that already has one or more image views.
My suggestion would be to add the image view to the cell in the cell prototype, perhaps in your storyboard or in the cell's initializer. Have your -collectionView:cellForItemAtIndexPath: set the image for that image view to the correct image for the given path.
What's happening is that UICollectionView reuses cells. So in didSelectItemAtIndexPath: you set the cell background, but then the UICollectionView reuses that same cell as needed (and you're not resetting the cell.backgroundView in cellForItemAtIndexPath:).
The way to fix this is to maintain an NSIndexSet of selected cells. In didSelectItemAtIndexPath: you can add the index of the item that was selected, and then force a reload of that item by calling reloadItemsAtIndexPaths. Then, in your cellForItemAtIndexPath: check the index set to see if the selected index is included, and if so, set the backgroundView of the cell.
I had the same issue few days ago & I posted a question here. Here is the answer I got & it works for me.
Collection View Cell multiple item select Error
And also if you are using a custom cell you can add this code to the init method of that cell & it will work too.
CGFloat borderWidth = 6.0f;
UIView *bgView = [[UIView alloc] initWithFrame:frame];
bgView.layer.borderColor = [UIColor redColor].CGColor;
bgView.layer.borderWidth = borderWidth;
self.selectedBackgroundView = bgView;