How do I clear a cell completely when I reuse it? - objective-c

When I call [table reloaddata];
The cells get redrawn with new data, but my UILabels get messed up because they are drawn over the old UILabels, so its a mess.
static NSString* PlaceholderCellIdentifier = #"PlaceholderCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PlaceholderCellIdentifier] autorelease];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor clearColor];
}
Is my Init of the cell.
I add a UILabel like so
UILabel *theDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 35,140, 20)];
[theDateLabel setBackgroundColor:[UIColor clearColor]];
[theDateLabel setTextColor:[UIColor lightGrayColor]];
[theDateLabel setText:[dateFormatter stringFromDate:theDate]];
[theDateLabel setFont:[UIFont fontWithName:#"TrebuchetMS-Bold" size:15]];
[cell addSubview:theDateLabel];
[theDateLabel release];
There are a few more labels in the cell, same thing.
What I would like to happen is that the old labels disappear from the cell so that they are no longer visible.

You should not add theDateLabel as a subview of cell. You should add it as a subview of cell.contentView.
As yuji suggests, one way to implement this is to create a subclass of UITableViewCell with a property for each custom subview. That way you can easily get to the date label of a reused cell to set its text for the new row.
Another common approach is to use the tag property that every UIView has. For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* PlaceholderCellIdentifier = #"PlaceholderCell";
static const int DateLabelTag = 1;
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PlaceholderCellIdentifier] autorelease];
UILabel *theDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 35,140, 20)];
theDateLabel.tag = DateLabelTag;
theDateLabel.backgroundColor = [UIColor clearColor];
theDateLabel.textColor = [UIColor lightGrayColor];
theDateLabel.font = [UIFont fontWithName:#"TrebuchetMS-Bold" size:15];
[cell.contentView addSubview:theDateLabel];
[theDateLabel release];
}
NSDate *theDate = [self dateForRowAtIndexPath:indexPath];
UILabel *theDateLabel = [cell.contentView viewWithTag:DateLabelTag];
theDateLabel.text = [dateFormatter stringFromDate:theDate];
return cell;
}

While Richard's solution will work, if your cells have any other subviews they'll get removed as well. Also, allocating and initializing your subviews every time you draw a cell isn't necessarily optimal.
The standard solution here is to create a subclass of UITableViewCell with a property #dateLabel (and so on for the other labels). Then, when you're initializing a cell, if it doesn't have a #dateLabel yet you can give it a new one, otherwise you only have to set its text.

Related

UITableViewCell and disappearing separator

I try to implement my own simple style of cells in my UITableView and I have a problem with separator. Works great with normal view, but when i select a cell it disappears. I try to add to my customSelect view separator, but then I can't see the separator anywhere. How can I add a separator to selected cell?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyCellIdentifier = #"MyCellIdentifier";
UITableViewCell *cell = [wallMenuTableView dequeueReusableCellWithIdentifier:MyCellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyCellIdentifier];
MenuItemModel *mItem = [menu.menuPositions objectAtIndex:indexPath.row];
cell.textLabel.text = mItem.displayName;
cell.textLabel.textColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont fontWithName:#"ArialMT" size:16];
cell.textLabel.shadowColor = [UIColor blackColor];
cell.textLabel.shadowOffset = CGSizeMake(0.0, 1.0);
customSeparator = [[UIView alloc] initWithFrame:CGRectMake(0, (cell.frame.origin.y), 320, 2)];
customSeparator.backgroundColor=[UIColor blackColor];
[customSeparator.layer setShadowOffset:CGSizeMake(0.0, 0.8)];
[customSeparator.layer setShadowOpacity:0.8];
[customSeparator.layer setShadowRadius:0.8];
[customSeparator.layer setShadowColor:[UIColor grayColor].CGColor];
[cell.contentView addSubview:customSeparator];
customSelect = [[UIView alloc] initWithFrame:CGRectMake(0, (cell.frame.origin.y+2), cell.frame.size.width, cell.frame.size.height)];
//[customSelect addSubview:customSeparator];
customSelect.backgroundColor = [UIColor clearColor];
[cell setSelectedBackgroundView:customSelect];
}
return cell;
}
And current result:
Use a UIImageView instead of a simple UIView for your separator. Set the Image value (this is important!) instead of backgroundColor value and stretch the image with scale to fill.
Maybe your costumSelect is under the contentView of the Cell. I implemented such behaviour before, but I subclassed UITableViewCell. Try to override setSelected method on your custom cell.
use tableView.separatorColor (and tableView.separatorStyle) to set a contrasting separator color. If you're drawing your own separators within the cell, set separatorStyle=UITableViewCellSeparatorStyleNone. Furthermore, setting the selectionStyle to UITableViewCellSelectionStyleNone will likely help you

How to change one UITableViewCell when it is touched

I have a table view cell with multiple images in them. When touching the images they shold display an overlay on top of the image which tells the user that this image was selected.
Is there a way to change the look of just one UITableViewCell without having to do a [tableView reloadData] which would allow me to style the cell differently in the table view datasource delegate method.
The way I would do it is to subclass UITableViewCell and then on tableView:didSelectRowAtIndexPath: get a reference to the cell and do whatever you want to it (or just target the image touch event if this is not a selection).
There might be another way of doing this without having to subclass, but I find myself subclassing UITableViewCell all the time and it's pretty straightforward to do.
If you wish to avoid subclassing, this can be achieved with gesture recognisers. Your question suggests a Tap and Hold user interaction on each image, which I have implemented in the code below. One point to remember, if the user is tapping and holding, they may not see the text you wish them to see.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ImageCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
UILongPressGestureRecognizer *recognizer2 = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Ben.png"]];
imageView.frame = CGRectMake(cell.contentView.bounds.origin.x,cell.contentView.bounds.origin.y , 100, 40);
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:recognizer];
[cell.contentView addSubview:imageView];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Steve.png"]];
imageView2.frame = CGRectMake(cell.contentView.bounds.origin.x + imageView.frame.size.width + 10,cell.contentView.bounds.origin.y , 100, 40);
imageView2.userInteractionEnabled = YES;
[imageView2 addGestureRecognizer:recognizer2];
[cell.contentView addSubview:imageView2];
[imageView release];
[imageView2 release];
[recognizer release];
[recognizer2 release];
return cell;}
- (void)imageTapped:(id)sender {
NSLog(#"%#", sender);
UILongPressGestureRecognizer *recognizer = (UILongPressGestureRecognizer *)sender;
if (recognizer.state == UIGestureRecognizerStateBegan) {
UILabel *label = [[UILabel alloc] initWithFrame:recognizer.view.bounds];
label.text = #"Pressed";
label.backgroundColor = [UIColor clearColor];
label.tag = 99999;
label.textColor = [UIColor whiteColor];
[recognizer.view addSubview:label];
[label release];
}
else {
[[recognizer.view viewWithTag:99999] removeFromSuperview];
}
}
Hope this helps.

Make a cell's background transparent, without also making the text transparent

I have a UITableView that I want to have a transparent background, but I can't seem to get that without making the text in the cells transparent as well. Here is what I have.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *labelString = #"Hello";
[cell setBackgroundColor:[UIColor darkGrayColor]];
cell.alpha 0.2f;
cell.textLabel.textcolor = [UIColor whiteColor];
cell.textLabel.text = labelString;
I have tried several other things such as setting the contentView's background color and alpha, as well as the backgroundView's color and alpha, nothing seems to work.
Instead of setting the cell.alpha,
cell.backgroundColor = [UIColor clearColor];
You may also need to set the table view background.
Placing this code in the -tableView:willDisplayCell:forRowAtIndexPath: solved the issue.
UIView *backView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
backView.backgroundColor = [UIColor clearColor];
cell.backgroundView = backView;

How can i put label into the table cell?

this is the cell i want to make the left side is cell.text and the right part is label.
Now the table style is
UITableViewStyleGrouped When i try to make the label i write these codes.
cell.textLabel.text = #"All";
UIView* view = cell.contentView;
UILabel* label1 = [[UILabel alloc] initWithFrame:cell.frame];
label1.textColor = [UIColor blackColor];
label1.textAlignment = UITextAlignmentCenter;
label1.text = #"%15";
[view addSubview:label1];
[label1 release];
But this doesnt work because cell of the label cover one and another.Can any one help me to make this kind of look with code of course.
The problem in your code seems to be the label1's frame. Change the its frame like the following.
CGRect lFrame = CGRectMake(cell.frame.width - 100, 0, 100, cell.frame.height);
UILabel* label1 = [[UILabel alloc] initWithFrame:lFrame];
Using exisiting style: The style you are using is already predefined. No need to add your custom label to the cell. You can achieve this style by specifying table cell's style to UITableViewCellStyleValue1.
[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 ....
You can change the font properties like style, color and size of the cell's textLabel and detailedTextLabel to fit your needs.
Just make your UITableviewCell type to UITableViewCellStyleValue1 and do like below.
cell.textLabel.text = #"All";
cell.detailTextLabel.text = #"%15";
You don't need to add view in the cell at all. Also, you can change textLable and DetailTextLabel properties whatever you want as you change with UILabel. They are UILabel itself. So you can do everything whatever you can do with UILabel.
Hope this help.
The pre-defined styles are great if they cover your needs.
Otherwise an approach like this one will work for cases where you want more power over the layout, or more views in the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [self makeCell: CellIdentifier];
}
MyData *data = [self.data objectAtIndex:indexPath.row];
UILabel *lbl1 = (UILabel *)[cell viewWithTag:1];
UILabel *lbl2 = (UILabel *)[cell viewWithTag:2];
lbl1.text = data.text;
lbl2.text = data.auxText;
return cell;
}
- (UITableViewCell *)makeLensListCell: (NSString *)identifier
{
CGRect lbl1Frame = CGRectMake(10, 0, 140, 25);
CGRect lbl2Frame = CGRectMake(10, 150, 140, 25);
UILabel *lbl;
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier] autorelease];
// Label with tag 1.
lbl = [[UILabel alloc] initWithFrame:lbl1Frame];
lbl.tag = 1;
[cell.contentView addSubview:lbl];
[lbl release];
// Label with tag 2.
lbl = [[UILabel alloc] initWithFrame:lbl2Frame];
lbl.tag = 2;
lbl.textColor = [UIColor lightGrayColor];
[cell.contentView addSubview:lbl];
[lbl release];
// Add as many labels and other views as you like
return cell;
}

Selected UITableViewCell changes background on Scroll

I have a UITableView with transparent background color, each of its cells have a custom background view, and gray selection style. The selection works fine, but when i select and drag the tableview up or down, the cell changes its background to transparent instead of the custom one. What shall i look to fix it?
EDIT: Source Code as requested by André Morujão
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
RestaurantInfo *restaurantInfo = [requestBean.restaurantArray objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
else {
cell = nil;
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
UIImageView *bgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
[bgView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"table_cell_bg.png"]]];
[cell setBackgroundView:bgView];
UILabel *restaurantNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 310, 15)];
[restaurantNameLabel setFont:[UIFont boldSystemFontOfSize:16]];
[restaurantNameLabel setText:restaurantInfo.restaurantName];
[restaurantNameLabel setBackgroundColor:[UIColor clearColor]];
[restaurantNameLabel setUserInteractionEnabled:NO];
[cell addSubview:restaurantNameLabel];
return cell;
}
Sorry, these aren't necessarily the cause for your problem, but start by doing these:
no need for the else block (or did you just put it there for debugging purposes?)
it should be enough to apply the selectionStyle and background inside the if block (unless you're changing them somewhere else)
the restaurantNameLabel should probably be added to the cell's contentView and not directly as a subview
you're leaking restaurantNameLabel and bgView; add [bgView release] and [restaurantNameLabel release] after you're done with them
Also, are you using a UIImageView for any reason in particular? It'd probably be enough to use a UIView, or even just to apply a backgroundColor.