i added my UICollectionView to the UITableViewCell (objective c), and the data is showing correctly in the collectionviews inside the tableview, the selection in the same collectionview is working as it expected ; the problem i have is:
if the user select one cell in collectionview (a) the label backgroundcolor of this cell is set to red
when the user select one cell in collectionview (b) the label backgroundcolor of this cell is set to red but the backgroundcolor of the previous selected cell in collectionview a is still
in red !
my question is how can i set clearColor to the previous selected cell ?
please help thank you
nb: the data and the number of collectionview are dynamic
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if(self.selectedIndex == indexPath.item)
{
cell.label.backgroundColor = [UIColor redColor];
}
else
{
cell.label.backgroundColor=[UIColor clearColor];
}
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
self.selectedIndex = indexPath.row;
}
Once you record or mark the state in UI, sometimes it's not simple way.
I suggest store the state in data model, and the cell's appearance is based on the data model, once the data model change, refresh the corresponding cell, that will work.
Here is a simple example:
in ViewController.m
in XXCellDataModel.h
in XXCollectionViewCell.h
in XXCollectionViewCell.m
Related
I have a problem with collection view cell. When my collection view first loaded, it display items like that:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
CalendarCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"CalendarCell" forIndexPath:indexPath];
[cell bindDate:_datesMgr.currentMonthItems[indexPath.row] andNowDate:_datesMgr.nowDate];
// bind events
if (_eventsMgr.eventsArray.count > 0){
for (int i = 0; i < _eventsMgr.eventsArray.count ; i ++) {
[cell bindConference:_eventsMgr.eventsArray[i]];
}
}
return cell;
}
Inside those methods are logic for adding subviews to custom cell class, which depend on certain circumstances.
Its all work, but, when collection view reloaded (i did force reload after 1 second) some of cells are reused and placed on others, therefore, it show "old" images and subviews.
I could see possible solution in forcing uicollection view to stop reusing cells (it is, load new cells every time). Is there any way to do this?
Try to implement prepareForReuse method for reset your old content in your custom UICollectionViewCell
-(void)prepareForReuse {
[super prepareForReuse];
self.yourimageview.image = nil; //and etc.
}
Introduction
I have a collectionView placed in my mainViewController with each DailyCell (custom UICollectionViewCell class) having two labels. I also have a Settings view controller that modifies the color of certain labels of the mainViewController, including those in the collectionViewController via a shared instance (singleton) of the viewController (.Vc). The settings pane changes the colors of all the other labels successfully, except for the ones present in the collectionView of which only two cells change.
Code
Here's the code for the collectionView in my mainViewController.m:
#pragma mark - UICollectionViewDataSource
// 2
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
// 1
return MIN([[WXManager sharedManager].dailyForecast count], 6) + 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
_cell = [collectionView dequeueReusableCellWithReuseIdentifier:DayCell forIndexPath:indexPath];
//Fetch Data
WXCondition *weather;
weather = [WXManager sharedManager].dailyForecast[indexPath.row];
averageWeather = (weather.tempHigh.floatValue +
weather.tempLow.floatValue)/2.0;
[_cell.labelTemp setText:[NSString stringWithFormat:#"%.0f°",
averageWeather]];
return _cell;
}
Here's the custom Daily Cell class code where the two labels are initialized:
if (self) {
s = [Singleton sharedInstance];
s.Dc = self;
// Initialize Label Day
[self.labelDay setTextColor:[UIColor lightGrayColor]];
[self.contentView addSubview:self.labelDay];
// Initialize Label Temp
[self.labelTemp setTextColor:[UIColor lightGrayColor]];
[self.contentView addSubview:self.labelTemp];
return self;
}
And here is the part in the settings where I try to change the color of those two labels depending on which static cell in the Settings is picked (i.e. when this cell is tapped in Settings, apply these colors to the labels in the viewController):
if ((indexPath.row == 1) && (indexPath.section==0)) {
//argentum
s.Dc.labelDay.textColor=[UIColor redColor];
s.Dc.labelTemp.textColor=[UIColor orangeColor];
}
if ((indexPath.row == 0) && (indexPath.section==0)) {
//album
s.Dc.labelDay.textColor=[UIColor lightGrayColor];
s.Dc.labelTemp.textColor=[UIColor lightGrayColor];
}
Visual Support
Question
Why is only one cell changing and not the rest?
Update 1
Continuously pressing a theme (sometimes) progressively updates the cell labels correctly. Still unsure what is causing this.
if indexPath.row is equal to zero means that the first element was selected (WED) if indexPath.row is equal to one then you're referring to the second element and so on. There's a method you should try: didSelectRowAtIndexPath
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
s.Dc.labelDay.textColor=[UIColor redColor];
s.Dc.labelTemp.textColor=[UIColor orangeColor];
}
I'm not completely sure tho, let me know!
My guess is that when you type s.Dc = self; in your daily cell, it removes the previous cell that you set at Dc property to replace it with the current one. And so you always have one cell linked to your singleton.
An other way to do it would be to store an enum (let's name it dayCellTheme) in you singleton. That you update when selecting a cell in your SettingsViewController.
Then in the cellForRowAtIndexPath datasource of your collectionViewController, you set the color of your labels accordingly to this property.
Now all you have to do is use a reloadData on your collection view when you leave the settingViewController.
Still i might be wrong about your problem. Let me know !
I faced an issue an take lot of time but cannot figure out the issue:
I created a UICollectionView with very simple content, one lable to indicate cell_number, and when a cell is selected, the background of cell is changed to orange.
I create a custom cell with xib file for design (very simple one). And I load this cell from my UICollectionView in my DemoUICVViewController.m file normally as many people did with some steps like:
- declare the custom cell class in ViewDidload:
[self.collectionView registerClass:[MyCustomCell class] forCellWithReuseIdentifier:#"MyCell"];`
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCell * myCell = (MyCustomCell*)[cv dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
myCell.lable.text = [arrayNumber objectAtIndex:indexPath.item];
return myCell;
}
and when selected:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// Get the cellForItemAtIndexPath and set the background coler of cell to orange
}`
Number of section I return 1, and number of item in section I return 10
All the cells in UICollectionView are display correctly. But when I tap to select a cell I see not only that cell is orange, but also some other cells also change to orange for e.g cell 5 and cell 9.
I debug but the didSelectItemAtIndexPath only get called once and at the right index, very strange when some other cells also be orange.
I am not sure if the problem is of Reusability of cell identifier, could someone give me some advise.
I attached photo for e.g here:
Image describes
Finally I found the root cause to fix: add this line to check to
collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
...
if(myCell.selected)
// set background of cell to orange;
else
// set white background;
...
}
I have a UICollectionView inside of a normal UIViewController.
Inside the collectionview I have designed the reusable UI for the collectionviewcells in storyboard.
Inside of the collectionviewcell there is a label that displays the cells indexpath.row and 5 UIButtons which if selected, change color and stay selected.
I have set up the collectionview so that if more that 30 cells are requested the collectionview will page horizontally, the collectionview layout is also horizontal.
The application runs nicely, scrolls properly and lays out cells correctly.
The problem I am having is when you select for example button A in cell 1 in the collectionviewcell (which is suppose to layout 100 cells) and page over two pages (60+ Cells) to page 3, button A in cell number 75 is selected. And further more if you scroll to the end (100 cells) and scroll back to page 3, button A in cell number 75 is on longer selected, but button A in cell number 64 is selected.
Here is some snippets of code:
cell.m - controls the action from the user.
- (IBAction)bubbleButtons:(id)sender {
for(UIButton *bubbleCell in self.bubbleButtons) {
if (bubbleCell.touchInside && !bubbleCell.selected) {
bubbleCell.selected = YES;
} else if (bubbleCell.touchInside && bubbleCell.selected) {
bubbleCell.selected = NO;
}
}
}
MainViewContoller.m - sets up cell from UICollectionViewCell made in storyboard
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Cell *cell1;
cell1 =[collectionView dequeueReusableCellWithReuseIdentifier:zCellID
forIndexPath:indexPath];
cell1.numMainLabel.text = [NSString stringWithFormat:#"%d |",indexPath.row+1];
return cell1;
I do not really understand what is wrong or what is causing this bug, I am assuming it has todo with the view being reloaded when a new part of the view becomes visible but that is just a guess. Help would be greatly appreciated.
Zach
It's probably because the reusable view is reused.
The proper way to do this is to create custom reusable view subclass.
And save the selection of those 5 button.
cell1 =[collectionView dequeueReusableCellWithReuseIdentifier:zCellID
This line here might or might not give you a new cell, it might give you a cell that is used before. So, you need to update the selection in there. Or it stay the same as the cell it's reusing.
The Uicollection only generate the cells that are been displayed at that moment, so when a cell disapier from the visible view, its been replace with the new one.
So when you seleted the cell 75 and you scroll down, until the cell 75 is no visible, and then you scroll back to cell 75, you are generating a new cell, with a new button that is not seleted because is new.
So what yo could do, is save which buttons had been selet, and in
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
ask if the button thats is been displayed at that moment need to be selected..
Hope its helps
I am just starting to implement a multiselect UICollectionView. Would the below be considered "safe" code (since i assume theres some reason it is called BackgroundView instead of AccessoryView or such) ? I had the idea to save some effort, i intend to keep track of the selected items at the indexpath for further use via an array.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//....
cell.selectedBackgroundView = someView_With_A_Checkmark_Image;
[cell bringSubviewToFront:cell.selectedBackgroundView];
//...
return cell;
}
Is it safe?? Ya of course it wont cause any error. If your backgroundView is above the contentView of the cell, then what is the significance of contentView??.
Collection view cell structure
If you select an item in the collection view, collectionView will switch the BackgroundView and Selected background view. So what you can do is give valid views as background view and selected background view upon configuring your custom cell or change any properties of the cell in didSelectItem to differentiate selection. That is better.
Then one more no need to keep track of selection using a separate array. [self.collectionView indexPathsForSelectedItems] will give you selected items path at any point of time