In my cellForRowAtIndexPath method I am using following if statements:
if ([taskitem.isCritical isEqualToString:#"iscritical"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor redColor];
}
else if ([taskitem.isUrgent isEqualToString:#"isurgent"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blueColor];
}
else if ([taskitem.isCompletedOK isEqualToString:#"iscompleted"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor greenColor];
UIButton *doneButton4 = [[UIButton alloc]initWithFrame:CGRectMake(0, 10, 12, 12)];
[doneButton4 setImage:[UIImage imageNamed:#"done"]forState:UIControlStateNormal];
[cell addSubview:doneButton4];
}
else {
cell.textLabel.textColor = [UIColor blackColor];
}
cell.textLabel.text = taskitem.taskName;
The problem is that the if statements are changing their behaviour if the user taps on any of the sections headers.
Do you find any error on my code that could be the reason of this weird behaviour or should I search for another reason in another method?
It looks like you're probably having a cell reuse problem. You need to make sure that anything you do in one case, is done for each case (or undone).
For example, in first your three conditions, you set the text colour and the background colour. But in the fourth case (the else) you only set the text colour, leaving the background colour to be whatever it was on this cell the last time it was used. You need to set the background colour in the else case as well. (Optionally, you can set all items back to defaults before the if).
You have a second problem here, with the third case, that creates and adds a button to the cell. But in the other cases, you do not remove that button if it exists. So when you get a cell that was used for a completed item earlier, you'll end up with a button that doesn't belong. Even if the cell is used for another completed item, you'll get two buttons on the same cell. One on top of the other (so it likely won't be visible, but it's still a problem).
Try using this code:
UIButton* oldButton = [cell viewWithTag:253];
if (oldButton)
{
[oldButton removeFromSuperview];
}
if ([taskitem.isCritical isEqualToString:#"iscritical"]) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor redColor];
}
else if ([taskitem.isUrgent isEqualToString:#"isurgent"]) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blueColor];
}
else if ([taskitem.isCompletedOK isEqualToString:#"iscompleted"]) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor greenColor];
UIButton *doneButton4 = [[UIButton alloc] initWithFrame:CGRectMake(0, 10, 12, 12)];
[doneButton4 setImage:[UIImage imageNamed:#"done"] forState:UIControlStateNormal];
doneButton4.tag = 253;
[cell addSubview:doneButton4];
}
else {
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = taskitem.taskName;
I don't recommend using tags like this in production code, but it's a quick way to see if it solves your problems. In real code, use a UITableViewCell subclass with a property for the done button that you can just show and hide. Ideally you're not creating it each time as that's an expensive operation and could slow down your scrolling performance.
Create doneButton4 in (cell == nil) when reuse cells in table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UIButton *doneButton4 = [[UIButton alloc]initWithFrame:CGRectMake(0, 10, 12, 12)];
[doneButton4 setImage:[UIImage imageNamed:#"done"]forState:UIControlStateNormal];
[cell addSubview:doneButton4];
doneButton4.tag=100;
}
UIButton *doneButton4=(UIButton*)[cell viewWithTag:100];
doneButton4.hidden=YES;
if ([taskitem.isCritical isEqualToString:#"iscritical"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor redColor];
}
else if ([taskitem.isCritical isEqualToString:#"isurgent"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blueColor];
}
else if ([taskitem.isCritical isEqualToString:#"iscompleted"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor greenColor];
doneButton4.hidden=NO;
}
else {
cell.textLabel.textColor = [UIColor blackColor];
}
cell.textLabel.text = taskitem.taskName;
}
Related
I am making an app which shows sport results and color codes them accordingly by setting their cell's background color:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Cell"];
if (_tabBar.selectedItem == _homeGamesItem) {
cell.backgroundColor = [UIColor whiteColor];
cell.detailTextLabel.text = #"";
cell.textLabel.text = [NSString stringWithFormat:#"Home Game %d", indexPath.row];
} else if (_tabBar.selectedItem == _myEventsItem) {
cell.backgroundColor = [UIColor whiteColor];
cell.detailTextLabel.text = #"";
cell.textLabel.text = [NSString stringWithFormat:#"My Result %d", indexPath.row];
} else if (_tabBar.selectedItem == _resultsItem) {
SportEvent *event = [self.appDelegate.user.resultSportEvents objectAtIndex:indexPath.row];
if ([event.gender isEqualToString:#""]) {
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", event.level, event.activity];
cell.detailTextLabel.text = event.result;
} else {
cell.textLabel.text = [NSString stringWithFormat:#"%# %# %#", event.gender, event.level, event.activity];
cell.detailTextLabel.text = event.result;
}
if ([[event.result substringToIndex:1] isEqualToString:#"W"])
cell.backgroundColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:.05];
else if ([[event.result substringToIndex:1] isEqualToString:#"T"])
cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:0 alpha:.05];
else if ([[event.result substringToIndex:1] isEqualToString:#"L"])
cell.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:.05];
}
if (_grayedOut) {
cell.textLabel.textColor = [UIColor grayColor];
cell.detailTextLabel.textColor = [UIColor grayColor];
} else {
cell.textLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.textColor = [UIColor blackColor];
}
return cell;
}
The strange thing is that this causes some cells to have strange backgrounds right around the labels (my apologies for the massive image):
Why do only some cells get this strange darkening around the labels?
Since you use these cells in other tabs, and you only change some cell's background color to white (e.g. homeGames), then add the following code to make all reusable cells have the same color (clearColor) before actually using them again:
...
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Cell"];
//Add This Code
cell.backgroundColor = [UIColor clearColor];
//Also make labels same color just to be sure
cell.textLabel.backgroundColor = [UIColor clearColor]; //or whiteColor
cell.detailTextLabel.backgroundColor = [UIColor clearColor]; //or whiteColor
if (_tabBar.selectedItem == _homeGamesItem) {
...
I am using a slide in menu style which loads a UITableView. - ECSlidingViewController
I have about 7 cells in a table view setup as follows:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.contentView.backgroundColor = [UIColor colorWithRed:75.0/255.0 green:83.0/255.0 blue:102.0/255.0 alpha:1.0];
UIView *topSplitterBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width, 1)];
topSplitterBar.backgroundColor = [UIColor colorWithRed:62.0/255.0 green:69.0/255.0 blue:85.0/255.0 alpha:1];
[cell.contentView addSubview:topSplitterBar];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor colorWithRed:196.0/255.0 green:204.0/255.0 blue:218.0/255.0 alpha:1];
cell.textLabel.font = [UIFont systemFontOfSize:18.0f];
cell.textLabel.shadowColor = [UIColor colorWithRed:27.0/255.0 green:31.0/255.0 blue:41.0/255.0 alpha:1];
cell.textLabel.shadowOffset = CGSizeMake(0, 1);
UIView *selectedBg = [[UIView alloc] initWithFrame:cell.frame];
selectedBg.backgroundColor = [UIColor colorWithRed:50.0/255.0 green:56.0/255.0 blue:73.0/255.0 alpha:1];
cell.selectedBackgroundView = selectedBg;
What would be the best way to show a cell as the selectedBg if that is the currently displayed controller?
I can access the following for example:
if ([self.slidingViewController.topViewController isKindOfClass:[MESHomeViewController class]]) {
However, I am not sure where would be best practice to set this up? I can do it in the switch case for the cell label setup... For example:
switch ( indexPath.row ) {
case 0: {
if ([self.slidingViewController.topViewController isKindOfClass:[MESHomeViewController class]]) {
cell.contentView.backgroundColor = [UIColor colorWithRed:50.0/255.0 green:56.0/255.0 blue:73.0/255.0 alpha:1];
}
cell.textLabel.text = NSLocalizedString(#"LMGames", #"Left Menu - Games");
break ;
However, when a new item is selected from the menu I would need to reload the table each time, is that good? Completing a self.tableView reloadData each time a cell is selected, or is there a better way to approach this?
Two ideas for you:
Set the selectedBg in the didSelectRowAtIndexPath method in order to set the selected cell.
Keep an integer reference to the currently selected row and the previously selected row and then refresh only those rows by using a method similar to: How to reload and animate just one UITableView cell/row?
I hope that helps!
I have made a tableViewController. I want to give different images to the 1st and 7th index cell. This is a code snippet inside my cellForRowAtIndexPath delegate method. It initializes the cells properly in the beginning but when I scroll up and down several times then it also starts to give the "button4.png" in the accessory view of other cells.
UIImage *indicatorImage;
if(indexPath.row==0||indexPath.row==6)
{
indicatorImage = [UIImage imageNamed:#"button4.png"];
}
else
{
indicatorImage = [UIImage imageNamed:#"img-arrow.png"];
}
cell.accessoryView =
[[UIImageView alloc]
initWithImage:indicatorImage];
What can be the possible reason for this?
The complete code of the function is a little messy, but I am posting it here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
selection=self.tabBarController.selectedIndex;
static NSString *CellIdentifier = #"Cell";
UILabel *topLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImage *indicatorImage;
if(indexPath.row==0||indexPath.row==6)
{
indicatorImage = [UIImage imageNamed:#"button4.png"];
}
else
{
indicatorImage = [UIImage imageNamed:#"img-arrow.png"];
}
cell.accessoryView =
[[UIImageView alloc]
initWithImage:indicatorImage];
cell.accessoryView =
[[UIImageView alloc]
initWithImage:indicatorImage];
const CGFloat LABEL_HEIGHT = 20;
topLabel =
[[UILabel alloc]
initWithFrame:
CGRectMake(
2.0 * cell.indentationWidth,
0.5 * (tableView.rowHeight - 2 * LABEL_HEIGHT),
tableView.bounds.size.width -
4.0 * cell.indentationWidth
- indicatorImage.size.width,
LABEL_HEIGHT)];
[cell.contentView addSubview:topLabel];
topLabel.backgroundColor = [UIColor clearColor];
topLabel.shadowColor = [UIColor whiteColor];
topLabel.shadowOffset = CGSizeMake(0, 1);
topLabel.textColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
topLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
topLabel.tag=10;
cell.backgroundView =
[[UIImageView alloc] init];
cell.selectedBackgroundView =
[[UIImageView alloc] init];
}
}
else
{
topLabel = (UILabel *)[cell viewWithTag:10];
}
UIImage *rowBackground;
UIImage *selectionBackground;
rowBackground = [UIImage imageNamed:#"topAndBottomRow.png"];
selectionBackground = [UIImage imageNamed:#"topAndBottomRowSelected.png"];
if(indexPath.row==0||indexPath.row==6)
{
rowBackground = [UIImage imageNamed:#"topAndBottomRowSelected.png"];
selectionBackground = [UIImage imageNamed:#"topAndBottomRowSelected.png"];
topLabel.textColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
topLabel.font = [UIFont systemFontOfSize:20];
}
((UIImageView *)cell.backgroundView).image = rowBackground;
((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
NSString *object = _objects[indexPath.row];
NSString *str=[object description];
topLabel.text=[NSString stringWithFormat:#" %#",str];
return cell;
}
You are setting this image in your if (cell == nil) ... block in which you create and configure the cell. But you need to move this image setting outside of that if block because if the cell is being reused (ie you don't have to alloc and init), the old image will be reused. You should review anything inside that if statement for things that should change cell-by-cell, and move that outside of the if block.
When scrolling messes you up like this, it suggests that you're not completely initializing the contents of a REUSED UITableViewCell. While your code snippet says you do set it to something -- your result suggests that you aren't. You can look for that.
For instance, try setting the accessoryView to nil immediately after getting the cell and see if the problem goes away.
I got an app with UITableView. Every cell has accessory. But i cant set backgroundColor ti this cells.
I tried to set backgrounColors in this ways:
cell.contentView.backgroundColor =[UIColor redColor];
cell.backgroundView.backgroundColor = [UIColor redColor];
cell.backgroundColor = [UIColor redColor];
But only contentView work. How can i do it? Thnx
the second way cell.backgroundView.backgroundColor = [UIColor redColor]; is not that wrong. Unfortunately there is no backgroundView until you create one. You have to create an UIView and set it as background of the cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Cell"];
UIView *background = [[UIView alloc] initWithFrame:CGRectZero];
background.backgroundColor = [UIColor redColor];
cell.backgroundView = background;
}
我现在遇到了个问题,如何使uitableview cell 的背景色填满整个cell ,以下是我的代码。但它不能正常工作、、、
Picture shows:
How can I code that set the color fill in cell view?
My code is below, but it does not work well.
cell.contentView.backgroundColor =[UIColor groupTableViewBackgroundColor];
cell.backgroundColor=[UIColor groupTableViewBackgroundColor];
cell.backgroundView.backgroundColor =[UIColor groupTableViewBackgroundColor];
cell.textLabel.backgroundColor = [UIColor groupTableViewBackgroundColor];
cell.detailTextLabel.backgroundColor = [UIColor groupTableViewBackgroundColor];
it works!
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
[tableView setBackgroundColor:[UIColor groupTableViewBackgroundColor]];
return 1;
}