UIButton showing multiple times on UITableView when created dynamically in UITableViewCell - objective-c

After trying various options, and reading numerous answers on SO, I am posting this question hoping somebody can provide some insight or a solution to this problem:
iOS5.1, XCode 4.4.1, Storyboard, ARC
I have a "Grouped" tableview, with each cell containing bunch of labels, images and buttons. One of the label, Description label, for it the text can be large or small, which means if text is large I have to increase the size of the label accordingly and place the buttons below accordingly as well. I am able to do all this, but the problem is that buttons appears twice when I scroll past the first cell and keeps repeating as I scroll.
Here's the code, all I am doing is calculating the height of label based on text, resizing the label, and then placing the 3 buttons below the description label accordingly.
The code below is just for one button but this should give the idea of what i am doing. I have tried to do similar stuff in "willDisplayCell", in the custom cell class but still the 3 buttons keeps repeating when i scroll down in the tableview. PLease refer the screenshot, the first three buttons shouldn't even show.
I noticed that position of first 3 buttons is same as if it ignores the sizeIncrement, meaning "359.0f + sizeIncrement +20" minus the "sizeIncrement", "sizeIncrement"= the height of description label after calculation
I also noticed that if i do
float y = 359.0f + 20;
instead of this
float y = 359.0f + sizeIncrement +20;
the repetition of Buttons problem is gone.
P.S: I know this is not the best code, but I have been trying lot of stuff to solve the problem so not bothered with best practices etc at this point.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tipsid";
TipsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[TipsCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
id tip = [_tips objectAtIndex: [indexPath section]];
NSDictionary *tipForIndex = [_tips objectAtIndex: [indexPath section]];
float sizeIncrement = [Utility getLabelHeightForText:[tipForIndex objectForKey:#"tipDescripion"]
withWidth:285.0f
withFont:[UIFont systemFontOfSize:14.0f]];
// Here I Resize the Label, code below to create a button and position accordingly.
float y = 359.0f + sizeIncrement +20;
UIButton *likeButton = [[UIButton alloc] initWithFrame:CGRectMake(10, y, 80, 26)];
likeButton.tag = [indexPath section];
// add targets and actions
[likeButton addTarget:self action:#selector(likebuttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[likeButton setBackgroundImage:[UIImage imageNamed:#"likebutton.png"] forState:UIControlStateNormal];
[likeButton setImage:[UIImage imageNamed:#"likedButton.png"] forState:UIControlStateSelected];
// add to a view
[cell.contentView addSubview:likeButton];
.....similarly create 2 other buttons

You should move button creating into if (cell == nil) operator:
if (cell == nil)
{
cell = [[TipsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// like button
float y = 359.0f + sizeIncrement +20;
UIButton *likeButton = [[UIButton alloc] initWithFrame:CGRectMake(10, y, 80, 26)];
likeButton.tag = LIKE_BUTTON_TAG_UNIQUE_IN_CONTENT_VIEW; // <<<<<<<<<<----------------
// add targets and actions
[likeButton addTarget:self action:#selector(likebuttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[likeButton setBackgroundImage:[UIImage imageNamed:#"likebutton.png"] forState:UIControlStateNormal];
[likeButton setImage:[UIImage imageNamed:#"likedButton.png"] forState:UIControlStateSelected];
// add to a view
[cell.contentView addSubview:likeButton];
// other buttons
}
// and here you can adjust button positions
UIButton *likeButton = [self.contentView viewWithIndex:LIKE_BUTTON_TAG_UNIQUE_IN_CONTENT_VIEW];

Related

How can I show custom image in UITableView accessory view in Objective-C?

I am doing a project in Objective-C. My problem is now,
Suppose I have a UITableView I want when I select a row it can show image with current position of user and remaining rows no need to show the same image.
I tried with lot of examples but no use.
can anyone help me? please...
Upon row selection, you should grab a cell and create your custom accessory view with that cell:
UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:indexPath];
BOOL bSelected = YES;
[self createAccessoryView:cell :bSelected];
Note however that bSelected bool above should ideally come from your model array, the array that holds your table view objects. Upon row selection, it will simply negate its value, such as:
bSelected = !bSelected;
Your createAccessoryView would look something like this:
- (void) createAccessoryView : (UITableViewCell *) cell :(BOOL)bSelected
{
UIImage * image = bSelected ? [UIImage imageNamed:#"check"] : [UIImage imageNamed:#"uncheck"];
cell.accessoryType = UITableViewCellAccessoryNone;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, 40, 40);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
//Uncomment below line if necessary
//[button addTarget:self action:#selector(accessoryButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
}
Off course, substitute your own image names above.
If you need more functionality in table view with some ready-made customisations (search, select, delete), take a look at this ViewController developed by me on github.
First of all place an image view in your cell, and put it as imgView.hidden = YES. When you select the cell, the image view of that cell to be unhide.
//Sample Code
IndexSelected = 99999 // In viewdidload
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
IndexSelected = indexpath.row;
[tbl reloaddata];
}
-(nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
if(IndexSelected == indexpath.row){
cell.imgView.hidden = NO;
}

UITableView overlaps cells after scrolling

All, I have a UITableView to which I add cells on user input. My cells have a slight transparency, and I recently noticed that after I have more cells than fit the screen, when I scroll down and back up, the cells which were momentarily off-screen now have new cells positioned behind them!
This shows up in my app, and also is evidenced in the view hierarchy debugger.
Interesting to note that it only happens when two or more cells scroll off screen (notice the count skips cell 7, which is at the bottom, just off the screen at the moment.
I figure this has something to do with caching the UIScrollView data for quicker loads? How do I stop it?
Adding a cell:
NSArray *indexPaths = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:numberOfCounters inSection:0], nil];
[counterTable insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationBottom];
numberOfCounters++;
[counters addObject:[[CKCounter alloc] init]];
cellForRowAtIndexPath: method
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"CKCounter";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
CKCounter *counter = [counters objectAtIndex:indexPath.row];
[counter setCurrentCount:indexPath.row];
[counter setIndex:indexPath.row];
[cell.contentView addSubview:[counter view]];
[cell.contentView setAutoresizesSubviews:TRUE];
[cell setBackgroundColor:[UIColor clearColor]];
/** Sets up the bounds for the subcounters **/
CGRect frame = cell.contentView.bounds;
frame.size.height -= counterMargins; // This will give the counters an inset
frame.size.width -= counterMargins; // The gap will be split to each side
frame.origin = cell.contentView.bounds.origin;
counter.view.frame = frame;
counter.view.opaque = false;
counter.view.center = cell.contentView.center;
//[NSString stringWithFormat:#"%lu", (unsigned long)[indexPath indexAtPosition:0]]
return cell;
}
See also: This Question

UITableViewCell with UILabel subview caching issue

First of all, please don't tell me this is a duplicate. I know this question has been asked and answered many times but I still can't seem to get my code to work even after reading everyone else's solutions.
I'm having an issue with my UITableViewCell that contains a UILabel subview. The UILabel sometimes doesn't appear in certain cells until I scroll away from those cells and return to them. Here is the code I am using to customize the cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *label;
if (cell == nil) {
// cell is nil, create it
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
label.tag = 888;
} else {
label = (UILabel*)[cell.contentView viewWithTag:888];
[label removeFromSuperview];
}
label.text = #"Label Text";
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
label.center = CGPointMake(cell.contentView.frame.size.width-label.frame.size.width/2-20, cell.contentView.frame.size.height/2);
[cell.contentView addSubview:label];
// customize cell text label
cell.textLabel.text = #"Cell Text";
cell.textLabel.textColor = [UIColor darkGrayColor];
return cell;
}
It appears as though the label shows up correctly when dequeueReusableCellWithIdentifier:CellIdentifier returns a non nil value but does not show up if the return value is nil and a new cell must be instantiated.
If anyone has an idea of why this might be happening, help would be greatly appreciated.
I see a couple of things you want to do.
1) read up on "sizeToFit" - the description says if the view has no superview you may get weird results.
2) When you create the view, add it to the cell immediately.
3) After you resize the cell, get its size, then compute the proper frame - I'd suggest not using "center" but I do not know that your code won't work for a fact.
4) Before even changing the center to changing the frame, hard code something like this:
CGRect r = label.frame;
r.origin = (CGPoint){ 20, 20 };
label.frame = r;
This will at least convince you that new cells and old cells are working properly. Then you can compute the frame you really want, or further play with center.
Not sure of the cause of your problem, but there are some improvements you could make. Maybe one of them fixes the issue:
In the dequeu scenario, you remove the label from the view, only to add it back. Instead, you should leave it in the view hierarchy.
To avoid having to resize and move the label all the time. Why not make it sufficiently wide, set the text right aligned. That way, you don't have to resize of move the label in the dequeue scenario.
It seems that the issue may be with modifying cell.textLabel. Other posts on this site have suggested that any time this label is modified, a new label is actually created and added to the cell's contentview (as opposed to just modifying the existing label). Setting cell.textLabel.backgroundColor = [UIColor clearColor]; seems to have fixed the problem
I'm still a bit confused about this though because even adding my custom label subview last (after setting properties for cell.textLabel) didn't fix the problem - the background color of cell.textLabel had to be set to transparent/clear.
There are three things out of place:
if (cell == nil) { // cell is nil, create it
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
label.tag = 888;
[cell.contentView addSubview:label]; // (1) DO THIS HERE
} else {
label = (UILabel*)[cell.contentView viewWithTag:888];
// (2) DON'T DO THIS: [label removeFromSuperview];
}
label.text = #"Label Text";
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
label.center = CGPointMake(cell.contentView.frame.size.width-label.frame.size.width/2-20, cell.contentView.frame.size.height/2);
// (3) DON'T DO THIS HERE: [cell.contentView addSubview:label];
....
I assume ARC is on, otherwise you need a [label release] after adding it to the contentView.

IOS UITableViewCell Spacer (or margin)

I'm trying to get a space between my table custom view cells on my table view controller. For example, for each cell created it is stacked up one by one and there is no margin. For example on the facebook iPhone app has a spacer after each cell which i would like to create, any ideas guys?
Edit: From comment below
The code looks like this
MSRSalesCompanyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.backgroundView = [[CustomCellBackground alloc] init];
NSDictionary *company = [companies objectAtIndex:[indexPath row]];
cell.companyName.text = [company objectForKey:#"Name"];
cell.backgroundColor = [UIColor clearColor];
cell.backgroundView.bounds = CGRectMake(0, 0, 320, 55);
[self loadImageAsync:cell withImageUrl:imageURL];
Check my answer for the similar question, it suggests you to create the invisible cells between the cells you want to divide with some space.
Option 2 is to create only the visible cells, make their height above the visible area and prepare special content and selected view's, note the selected view creation is not so easy and you'll need to do it as you probably don't want the spacing area to get selected, so i'm using the first option when there's a need to get some cell's spacing.
The main (and probably the only) disadvantage of the first option is that you have to treat the cell's indexes in a special way to distinguish the spacing-cells and the visible-cells.
If your tableView's rowHeight is 50 points, make your background image view height say, 40 points, and centre it in the cell. Then make your cell background colour [UIcolor clearColor]
Okayy i did some thing like this.....
First the BGColor Of view which will hold the Tableview is set to White (it was a personal choice w.r.t to my design) and then the cellForRowAtIndexPath method looks some thing like this.
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
cell = nil;
//Create Cell
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
//Retrive Values From DB
DBTable_Description *dbObject = [[DBTable_Description alloc]init];
dbObject = [contentList objectAtIndex:[indexPath row]];
//Cell View
UIView *cellView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 65)];
//ImageView
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(4.0, 8.0, 300.0, 58.0)];
imageView.userInteractionEnabled = NO;
imageView.image = imgForCellBkg;
//Label
UILabel *lblFor = [[UILabel alloc]initWithFrame:CGRectMake(70, 25, 200, 21)];
lblFor.text =dbObject.field1;
lblFor.backgroundColor = [UIColor clearColor];
lblFor.font = [UIFont fontWithName:#"Helvetica Neue" size:16];
lblFor.textColor = [UIColor grayColor];
lblFor.shadowColor = [UIColor grayColor];
//Adding Views to Cell View
[cellView addSubview:imageView];
[cellView addSubview:lblFor];
[cell.contentView addSubview:cellView];
cell.selectionStyle = NO;
return cell;
}
Okay First and formost neglect the Database code.
Now what i did is i created a View on each Cell name cellView (set the height as per ur requirement) next i had an Image View and set the appropriate image (again it may not be the thing u want to do) but pay attention to the CGRectMake i se the values according to the amount of gap i want b.w my cells.. the rest is usual.
here is the image of the view i had in my App
Let me Know if it worked
Cheers
W

Put a UIButton inside a UITableView

I am trying to put a UIButton inside a UITableViewCell.
The UITableView also has cells containing UILabels and and the cells have gradient backgrounds being drawn into them. The problem I am seeing is that my UIButton is just a filled black cell with no text display, and changing both the color and background color properties does not appear to do anything.
Here's the code I use to create the button:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"InAppViewController, doing this - width= %f", self.wdth);
static NSString *ProductTableIdentifier = #"ProductTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ProductTableIdentifier];
if (cell == nil)
{
if (self.wdth >= 700) {
CGRect cellFrame = CGRectMake(0, 0, (self.wdth - 100), 40);
cell = [[[UITableViewCell alloc] initWithFrame:cellFrame reuseIdentifier: ProductTableIdentifier] autorelease];
// Set up some labels...
CGRect seenValueRect = CGRectMake(self.wdth-320, 0, 100, 40);
UIButton *seenValue = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[seenValue setBackgroundColor:[UIColor greenColor]];
seenValue.tag = kSeenValueTag;
seenValue.frame = seenValueRect;
[seenValue setTitle:#"I'm a clone" forState:UIControlStateNormal];
[cell.contentView addSubview:seenValue];
[seenValue release];
// Continue setting up cell...
The pastebin link contains the code to the entire cellForRowAtIndexPath() function (for the UITableView in question).
http://pastebin.com/bpEyfruE
Maybe the problem is that you're releasing the UIButton innitialized with convenience initializer [UIButton buttonWithType:(UIButtonType)]. Try removing the [button release]
It can't even be that you have to do [cell addSubview:seenValue]; instead of [cell.contentView addSubview:seenValue];
You could also try to do CGRectMake(110, 11, 185, 30) instead of CGRectMake(self.wdth-320, 0, 100, 40): I use it and it works well but I don't know if it what you need