iPhone + UITableView + format cells - iphone

I am using following method in my application:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 0)
{
cell.contentView.backgroundColor = [UIColor lightGrayColor];
cell.contentView.alpha = 0.5;
}
}
When I run the application I have 7 rows in my table. According to above function only the cell of first row (row number 0) should be formatted (because of the if condition).
Cell of 1st row (row number 0) is formatted properly (as per desired output). But if I scroll the table down one more cell is displayed as formatted: cell at row number 5.
Why so?

I agree with Vladimir's answer.
However, i also believe you should follow a different approach.
In the current situation you are formatting your cell frequently, as the method gets called in each scroll, and this leads you to a suboptimal performance.
A more elegant solution is to format 1st row differently than others only "once" : when you create your cells.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier;
if(indexPath.row == 0)
CellIdentifier = #"1stRow";
else
CellIdentifier = #"OtherRows";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if(indexPath.row == 0){
cell.contentView.backgroundColor = [UIColor lightGrayColor];
cell.contentView.alpha = 0.5;
// Other cell properties:textColor,font,...
}
else{
cell.contentView.backgroundColor = [UIColor blackColor];
cell.contentView.alpha = 1;
//Other cell properties: textColor,font...
}
}
cell.textLabel.text = .....
return cell;
}

I think the reason is that TableView reuses already existing cells and displays them if it is possible. What happens here - when table is scrolled and row 0 becomes invisible then itscorresponding cell is used for a newly displayed row. So if you're reusing cells you must reset their properties:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 0) {
cell.contentView.backgroundColor = [UIColor lightGrayColor];
cell.contentView.alpha = 0.5; }
else
{
// reset cell background to default value
}
}

Related

change the appearance of a single UITableViewCell based on the content

I have a problem with a UITableView with custom UITableViewCell.
The table is filled by an NSArray, and I want that if an object in this NSArray begins with - changes its appearance.
the problem is that the UITableViewCell that begins with - is changed, but also change other cells that should not change.
this is my code:
//this is the way in which change the height of the cell if the object in the array begins with -
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *try = [arrayTitleEs objectAtIndex:indexPath.row];
if ([[try substringToIndex:1]isEqualToString:#"-"]) {
return 45;
}
else return 160;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellCardioScheda";
CardioSchedaCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.titleEs.text = [arrayTitoloEs objectAtIndex:indexPath.row];
NSString *try = [arrayTitoloEs objectAtIndex:indexPath.row];
if ([[try substringToIndex:1]isEqualToString:#"-"]) {
cell.titleEs.frame = CGRectMake(0, 0, cell.frame.size.width-15, cell.frame.size.height);
}
return cell;
}
as you can see from the picture that begins with the cell - is smallest and the text is moved to the left, in the next cell is all right, but the text in the last cell is moved, but should not!
thanks to all
In cellForRowAtIndexPath you can create two different types of cells and return one or the other according to your needs:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *firstCell = [tableView dequeueReusableCellWithIdentifier:#"firstCellID"];
if (firstCell == nil) {
firstCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"firstCellID"] autorelease];
}
// Set here firstCell
UITableViewCell *secondCell = [tableView dequeueReusableCellWithIdentifier:#"secondCellID"];
if (secondCell == nil) {
secondCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"secondCellID"] autorelease];
}
// Set here secondCell
if ([[try substringToIndex:1]isEqualToString:#"-"]) {
return secondCell;
} else {
return firstCell;
}
}
The problem is with the following:
if ([[try substringToIndex:1]isEqualToString:#"-"]) {
cell.titleEs.frame = CGRectMake(0, 0, cell.frame.size.width-15, cell.frame.size.height);
}
You need an else to set the frame properly if the condition isn't met. Cells get reused. Anything you do to a cell must be done for all cells.
if ([[try substringToIndex:1]isEqualToString:#"-"]) {
cell.titleEs.frame = CGRectMake(0, 0, cell.frame.size.width-15, cell.frame.size.height);
} else {
cell.titleEs.frame = CGRectMake(...); // whatever regular cells should be
}
BTW - you could replace [[try substringToIndex:1]isEqualToString:#"-"] with [try hasPrefix:#"-"].

uitableviewcell alternating background cell colors even for cells without data

I know how to set alternating colors to a tableviewcell, but how can I set all the visible rows to have an alternating color? For instance, right now if I only have 2 cells with data, only 2 cells will have background colors - how do I fill the backgrounds of the empty cells too?
try doing some thing like this:
(a)Add only required number of dummy rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if ([UIAppDelegate.getwaitlistArray count]>=numberOfVisibleRowsOnYourScreen) {
return [UIAppDelegate.getwaitlistArray count];
}
else{
return ([UIAppDelegate.getwaitlistArray count] + numberOfVisibleRowsOnYourScreen - [UIAppDelegate.getwaitlistArray count]);
}
}
(b)Alternare your cell:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
//alternating cell back ground color
if (indexPath.row%2 == 0) {
[cell setBackgroundColor:[UIColor colorWithRed:237.0/255.0f green:237.0/255.0f blue:237.0/255.0f alpha:1.0f]];
}else
{
[cell setBackgroundColor:[UIColor colorWithRed:247.0/255.0f green:247.0/255.0f blue:247.0/255.0f alpha:1.0f]];
}
}
(c)in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyIdentifier"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
//Create your lables/buttons/text/image
nameLabel.test=#"Whatever"; ..... ......
......
if (indexPath.row < [YourArray count]) { Populate your data here in the cells } else { cell.userInteractionEnabled=FALSE; nameLabel.text=#""; } return cell; }
Add dummy cells to the end of your list.

How to create a table view with only one row selectable

Hi need to create a table view with only one cell selectable like this img.
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"CellWithSwitch"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CellWithSwitch"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.font = [UIFont systemFontOfSize:14];
if(indexPath.row == 0)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
cell.textLabel.text = #"Sound Effects";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)path {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];
if(path.row == 0)
{
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
}
if you like only one row selectable you have to manage this in the methods of the table:
in - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
you need to implement the selection logic. if you click on a non-selected object, you select it and deselect all others, or only the one that is currently selected (if there is one selected). If you click on a selected object, just deselect it here
dont forget to do [theTableView reloadData];
in case your screen does not update if you change something in the table's content
then to redraw you just ensure that your method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
ensures that the object which is selected is marked somehow. This way you can also do nice things like showing a toggle ON/OFF button or anything you may whish.

UITable load first UITableViewCell for my last row of UITableViewCell

While coding with UITableView, I encounter this bug that I couldn't understand. I got 3 rows for my table and setting 50px for each row, except the 2nd row that I set it 500px which fill the whole screen. Problem comes when I scroll down to bottom, my bottom role is repeating first row appearance.This is my custom code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 3;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TestTable";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if (indexPath.section ==0 && indexPath.row==0) {
cell.contentView.backgroundColor = [UIColor redColor];
}
if (indexPath.section ==0 && indexPath.row==1) {
cell.contentView.backgroundColor = [UIColor blueColor];
}
if (indexPath.section ==0 && indexPath.row==2) {
cell.contentView.backgroundColor = [UIColor greenColor];
}
}
// Configure the cell...
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row==1) {
return 400;
}
return 50;
}
According to the code, first row is red color, second role is red and third one is blue. But my last row is red color (repeating the first row). If I set my 2nd row to shorter than the screen, e.g. 100px, third row loading fine.
Original Display
After Scroll Down
Appreciate for all kind of advice, as I am running out of ideas how is this happening.
Thanks
When 2nd row is long first row becomes invisible and its cell is reused in last row. That's why you should configure cell each time tableView:cellForRowAtIndexPath: is called i.e. after if (cell == nil) {...} block:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TestTable";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
if (indexPath.section == 0 && indexPath.row==0) {
cell.contentView.backgroundColor = [UIColor redColor];
}
if (indexPath.section ==0 && indexPath.row==1) {
cell.contentView.backgroundColor = [UIColor blueColor];
}
if (indexPath.section ==0 && indexPath.row==2) {
cell.contentView.backgroundColor = [UIColor greenColor];
}
return cell;
}

UITableView's background color becoming white when section is empty

Here is the deal: I have a UITableView with 2 sections, and I want to display a "no data" cell when the first section is empty, so that the 2 section headers are not stuck together (cause it looks weird).
It works great (even though I had trouble making it work at first, see this thread). I'm using viewForFooterInSection :
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
if(section == 0)
{
if([firstSectionArray count] == 0)
return 40;
else
return 0;
}
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
if(section == 0)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 10, 50, 44)];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor colorWithWhite:0.6 alpha:1.0];
label.textAlignment = UITextAlignmentCenter;
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
label.text = #"No row";
return [label autorelease];
}
return nil;
}
But the background color turns plain white when I display the section footer view. See image:
alt text http://img683.yfrog.com/img683/9480/uitableviewproblem.png
I like it better when the background is filled with empty cells. Does anyone have any idea how to do that? Thanks
The background is filled with empty cells when you have no footer. So do not implement a viewForFooterInSection (or titleForFooterInSection) method, and you will get the "empty cells" effect.
I'd recommend that you return a cell indicating that there are no entries to show, like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (matches.count>0) {
// Do your usual thing here
} else {
static NSString *cellId = #"noDataCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId] autorelease];
cell.textLabel.textAlignment = UITextAlignmentCenter;
cell.textLabel.textColor = [UIColor grayColor];
}
cell.textLabel.text = #"Aucun match";
return cell;
}
}
And of course, you would have to tell UIKit that you always have at least one cell in your section... I've added the isDeletingRow case that seems to trouble you (in comment).
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section==0) return matches.count>0 ? matches.count : (isDeletingRow ? 0 : 1);
// Set 'isDeletingRow' to YES when a delete is being committed to the table, in that case we let UIKit know that we indeed took care of the delete...
// And cover the other sections too...
}
When you are committing the edits, you need to set isDeletingRow for numberOfRowsInSection to return a satisfactory value...
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
isDeletingRow = YES;
// Your current code when a row is deleted here...
isDeletingRow = NO;
if (matches.count==0) [self.tableView performSelector:#selector(reloadData) withObject:nil afterDelay:0.5];
}
}