I'm having some problem with UIButton in a UITableViewCell.
I have created a custom tableviewcell in storyboard, using the prototype cell.
There are two buttons and I have set a tag to them.
The first time the table view is drawn everything is displayed correct, but if I scroll or update the data and call reloadData on tableview, it's not updated correct.
Code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Moment Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSLog(#"Cell: %#", cell);
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
NSArray *row = [mMoment objectAtIndex:indexPath.row];
UILabel *label;
label = (UILabel *)[cell viewWithTag:101];
label.text = [row objectAtIndex:0];
label = (UILabel *)[cell viewWithTag:102];
label.text = [NSString stringWithFormat:#"Koeff: %#",[row objectAtIndex:2]];
UIButton *button;
NSString *btn_title;
button = (UIButton *)[cell viewWithTag:104];
NSLog(#"Button: %#", button);
[button setTag:1];
btn_title = [NSString stringWithFormat:#"%#", [row objectAtIndex:4]];
[button setTitle:btn_title forState:(UIControlState)UIControlStateNormal];
[button addTarget:self action:#selector(poangButtonClick:event:) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"Row: %d, PoƤng: %#", indexPath.row, btn_title);
label = (UILabel *)[cell viewWithTag:103];
label.text = btn_title;
button = (UIButton *)[cell viewWithTag:105];
[button setTag:2];
btn_title = [NSString stringWithFormat:#"%#", [row objectAtIndex:5]];
[button setTitle:btn_title forState:(UIControlState)UIControlStateNormal];
[button addTarget:self action:#selector(poangButtonClick:event:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
The first time button = (UIButton *)[cell viewWithTag:104]; is called on every visible row, everything is correct, but if I scroll or reload the view, button is nil?
Why? Retrieving a label the same way works, and is displayed correctly.
How can I change the label of the buttons in the cell?
Regards
/Fredrik
A quick guess: I see you are resetting the buttons "tag" value which you use to refere to it. So you cant retrive it (after changing it) anymore with the value 104 (after the first creation it is now 1 and 2)
[button setTag:1];
so, you wont get it the next time via
button = (UIButton *)[cell viewWithTag:105];
My assumption is that that the cell does not get deallocated and thus this tag value stays. Maybe this will solve it.
Related
I want a button to show when i select a cell, when i select the same cell or another cell i want the button to hide. So one button should only be visible at a time.
What i have:
in my .h file:
#property (strong, nonatomic) NSIndexPath *isselectednow;
and my .m file:
Viewdidload:
self.isselectednow = [NSIndexPath indexPathForRow:7 inSection:1];
cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//[cell addSubview:[self drawSeparationView:(indexPath.row)]];
UILabel *DateName = (UILabel *)[cell viewWithTag:100100];
DateName.textColor = [UIColor blackColor];
//DateName.text = [NSString stringWithFormat:#"%ld",(long)indexPath.row ];
DateName.text = objects[indexPath.row];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(buttonOnCellPressed:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Update" forState:UIControlStateNormal];
button.frame = CGRectMake(DEVICE_SIZE.width - 60, 18, 55, 15);
[cell addSubview:button];
if ([indexPath compare:self.isselectednow] == NSOrderedSame) {
button.hidden = NO;
}
else{
button.hidden = YES;
}
UILabel *lbl1 = (UILabel *)[cell viewWithTag:100101];
lbl1.textColor = UIColorFromRGB(0x141414);
UILabel *lbl2 = (UILabel *)[cell viewWithTag:100102];
lbl2.textColor = UIColorFromRGB(0x141414);
UILabel *lbl3 = (UILabel *)[cell viewWithTag:100103];
lbl3.textColor = UIColorFromRGB(0x141414);
UILabel *lbl4 = (UILabel *)[cell viewWithTag:100104];
lbl4.textColor = UIColorFromRGB(0x141414);
UILabel *lbl5 = (UILabel *)[cell viewWithTag:100105];
lbl5.textColor = UIColorFromRGB(0x141414);
UITextField *breakfastName = (UITextField *) [cell viewWithTag:100200];
breakfastName.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:#"Name here"
attributes:#{NSForegroundColorAttributeName:UIColorFromRGB(0x141414)}];
breakfastName.textColor = UIColorFromRGB(0x141414);
[breakfastName setDelegate:self];
//[breakfastName addTarget:self action:#selector(textChanged:) forControlEvents:UIControlEventEditingChanged];
UITextField *OutName = (UITextField *) [cell viewWithTag:100201];
OutName.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:#"Name here"
attributes:#{NSForegroundColorAttributeName:UIColorFromRGB(0x141414)}];
OutName.textColor = UIColorFromRGB(0x141414);
[OutName setDelegate:self];
UITextField *lunchName = (UITextField *) [cell viewWithTag:100202];
lunchName.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:#"Name here"
attributes:#{NSForegroundColorAttributeName:UIColorFromRGB(0x141414)}];
lunchName.textColor = UIColorFromRGB(0x141414);
[lunchName setDelegate:self];
UITextField *InName = (UITextField *) [cell viewWithTag:100203];
InName.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:#"Name here"
attributes:#{NSForegroundColorAttributeName:UIColorFromRGB(0x141414)}];
InName.textColor = UIColorFromRGB(0x141414);
[InName setDelegate:self];
UITextField *eveningName = (UITextField *) [cell viewWithTag:100204];
eveningName.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:#"Name here"
attributes:#{NSForegroundColorAttributeName:UIColorFromRGB(0x141414)}];
eveningName.textColor = UIColorFromRGB(0x141414);
[eveningName setDelegate:self];
UITextField *othersName = (UITextField *) [cell viewWithTag:100205];
othersName.attributedPlaceholder =
[[NSAttributedString alloc]
initWithString:#"Name here"
attributes:#{NSForegroundColorAttributeName:UIColorFromRGB(0x141414)}];
othersName.textColor = UIColorFromRGB(0x141414);
cell.clipsToBounds = YES;
cell.accessoryType = UITableViewCellAccessoryNone;
cell.backgroundColor = UIColorFromRGB(0xf3f0e9);
return cell;
}
didSelectRowAtIndexPath:
[tableView beginUpdates];
if ([indexPath compare:self.isselectednow] == NSOrderedSame) {
self.isselectednow = nil;
}
else{
self.isselectednow = indexPath;
}
[tableView endUpdates];
//[tableView reloadData];
From the docs about beginUpdates:
Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously.
Although you've changed the isSelectedNow boolean, you haven't actually specified any insertion, deletion, or selection operations between beginUpdates and endUpdates. So you're not actually beginning or ending any updates to the cells' content with that code.
I'm not sure what you're trying to do, but taking out [tableView beginUpdates]; and [tableView beginUpdates]; and reinserting [tableView reloadData]; would result in a proper data reload.
Edit:
Aside from that, the problem is that you're reusing your cells with dequeueReusableCellWithIdentifier:, but you're adding a new UIButton subview each time, so you're basically putting each new UIButton over the old. I suggest doing what you've done for all your labels and textfields in cellForRowAtIndexPath: -- reuse your update button by adding it to your custom table view cell and accessing it with viewWithTag:.
i am making an app in which i am using checkboxes in uitableview cell. Now i am stuck on it how can i show count of selected checkboxes in a label. like i check one box then in label "1 checkbox selected" will shown and if i select 2 check boxes then in label "2 checkbox selected" will shown how it can be done any idea? below is my code where i am handling my checkbox button:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *tableviewidentifier = #"cell";
tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:11];
UILabel *msg = (UILabel *)[cell viewWithTag:12];
UILabel *date = (UILabel *)[cell viewWithTag:13];
UILabel *time = (UILabel *)[cell viewWithTag:14];
[valuedate setText:#"Demo"];
[msg setText:#"How are You?"];
date.text=#"14/07/2014";
time.text=#"A 08:16";
// [cell.textLabel setText:activityModel.userName];
valuedate.font=[UIFont fontWithName:#"SegoeUI" size:15];
msg.font=[UIFont fontWithName:#"SegoeUI-light" size:10.0];
date.font=[UIFont fontWithName:#"SegoeUI-light" size:9];
time.font=[UIFont fontWithName:#"SegoeUI-light" size:9];
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]])
{
[cell.button setImage:[UIImage imageNamed:#"tick.png"] forState:UIControlStateNormal];
//[cell.button setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
}
else
{
[cell.button setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
}
cell.button.tag=indexPath.row;
[cell.button addTarget:self action:#selector(checkButton:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
viewDidLoad
yourTableView.allowsmultiselection=YES;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
[cell.btn setBackgroundImage:[UIImage imageNamed:#"selected-24.png"] forState:UIControlStateNormal];
NSArray *arr=[tableView indexPathsForSelectedRows];
lbl.textLabel.text=[NSString stringWithFormat:#"%d",[arr count] ];
}
in deselect
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
[cell.btn setBackgroundImage:[UIImage imageNamed:#"unselected-24.png"] forState:UIControlStateNormal];
NSArray *arr=[tableView indexPathsForSelectedRows];
lbl.textLabel.text=[NSString stringWithFormat:#"%d",[arr count] ];
}
Take a NSMutableArray for selelcted buttons.when you select particuler button at that time add that indexpath.row value to the array.And when you delselect the button at that time check wheateher that indexpath.row value present in that array or not ,if yes then find the index of that object and remove that object from the array.
if([array containsObject:#"value"]){
int n=[array indexOfObject:#"value"];
[array removeObjectAtIndex:n];
}
Now check the count of array as [array count];
I have searched all over the web and cant seem to find a solution to this simple problem. I have a table view of buttons when the work "like". When the Button is pressed, it changes the word to "Unlike". I got it to work but when I scroll down the table, I see other buttosn also change to "unlike" and sometimes overlaps it with "Like". And when I scroll back up, the original button I selected changes back to normal state. I understand the cells are reusable and thats why I am using a mutable array for my data source and still it doesnt work. Please help!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton setTitle:#"Like" forState:UIControlStateNormal];
myButton addTarget:self action:#selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
myButton.frame = CGRectMake(14.0, 10.0, 125.0, 25.0);
myButton.tag =indexPath.row;
[cell.contentView addSubview:myButton];
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
return cell;
}
the action method:
-(void)tapped:(id)sender {
UIButton *senderButton = (UIButton *)sender;
UITableViewCell *parentCell = [[sender superview]superview];
NSIndexPath *indexPathLiked = [table indexPathForCell:parentCell];
[array replaceObjectAtIndex:senderButton.tag withObject:[NSNumber numberWithInt:1]];
[sender setTitle:#"Unlike" forState:UIControlStateNormal];
}
If the table calls the cellForRowAtIndexPath you create all the time a new button. When you get a reused cell the button still exists and you put a new one over there.
Change your method to:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton setTitle:#"Like" forState:UIControlStateNormal];
myButton addTarget:self action:#selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
myButton.frame = CGRectMake(14.0, 10.0, 125.0, 25.0);
myButton.tag =indexPath.row;
[cell.contentView addSubview:myButton];
}
else {
// todo: change the button title to "like" or "unliked" value
}
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
P.S. This make no sense, you doesn't use that, why you do that?
UITableViewCell *parentCell = [[sender superview]superview];
NSIndexPath *indexPathLiked = [table indexPathForCell:parentCell];
If you have only one section you can get the cell without using superview:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0]
UITableViewCell *parentCell = [table cellForRowAtIndexPath:indexPath];
I've got 3 uilabels added to a uitableview cell. The problem that I am running into is when I swipe to delete, my UILabel on the right side of the cell doesn't move so the delete button and the UILabel are overlapping each other. I've posted some of my code below.
I developed my layout using storyboard, so from what I am reading, frames aren't going to help.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *baseTableCellIdentifier = #"baseCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:baseTableCellIdentifier];
BaseInfo *infoAtIndex = [[[DataClass getInstance] allItems] objectAtIndex:[indexPath row]];
baseName = (UILabel *)[cell viewWithTag:1];
baseICAO = (UILabel *)[cell viewWithTag:2];
baseTime = (UILabel *)[cell viewWithTag:3];
[cell.contentView addSubview:baseName];
[cell.contentView addSubview:baseICAO];
[cell.contentView addSubview:baseTime];
[baseName setText:[infoAtIndex name]];
[baseICAO setText:[infoAtIndex icao]];
baseTimeZome = [NSTimeZone timeZoneWithName:[infoAtIndex timeZone]];
[baseDate setDateFormat:#"HH:mm"];
[baseDate setTimeZone:baseTimeZome];
NSString *baseTimeString = [baseDate stringFromDate:[NSDate date]];
[baseTime setFont:[UIFont boldSystemFontOfSize:20]];
[baseTime setText:baseTimeString] ;
return cell;
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated{
if (editing) {
//no idea what to put here
}else{
}
}
In your UITableViewCell subclass override setEditing:animated: and perform there any layout change. As the commenter says, you may not need to do that setting proper values for your label's autoresizingMask.
You should create a cell subclass. Then you can implement setEditing:animated: to modify the subviews frames.
I have a UITableView with 20 rows. In each row, two UIButtons are added, so totally I have 40 buttons. How can I access each button in each cell? All those UIButton have the two tags 1 and 2.
For example: I want to write a method to change the background color of 2 buttons in a particular row:
-(void)changeColor:(int)row{
//code here
}
Do you have any suggestion?
-(UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"] autorelease];
UIButton *button1=[[UIButton alloc] initWithFrame:CGRectMake(x1,y1,w1,h1)];
UIButton *button2=[[UIButton alloc] initWithFrame:CGRectMake(x2,y2,w2,h2)];
[button1 setTag:1];
[button2 setTag:2];
[[cell contentView] addSubview:button0 ];
[[cell contentView] addSubview:button1 ];
[button0 release];
[button1 release];
}
UIButton *button1 = (UIButton *)[cell viewWithTag:1];
UIButton *button2 = (UIButton *)[cell viewWithTag:2];
return cell;
}
You should be able to do this:
-changeColor:(int)row
{
NSIndexPath indexPath = [NSIndexPath indexPathForRow:row inSection:0]; // Assuming one section
UITableViewCell *cell = [myTableView cellForRowAtIndexPath:indexPath];
UIButton *button1 = (UIButton *)[[cell contentView] viewWithTag:1];
UIButton *button2 = (UIButton *)[[cell contentView] viewWithTag:2];
}
*some syntax might be wrong. I dont have Xcode handy
If you want to change the button color to have a highlighted / downstate I suggest to use the following:
[yourButton addTarget:self action:#selector(goToView:) forControlEvents:UIControlEventTouchUpInside];
[yourButton addTarget:self action:#selector(changeColor:) forControlEvents:UIControlEventTouchDown];
[yourButton addTarget:self action:#selector(touchCancel:) forControlEvents:UIControlEventTouchDragExit];
-(void)buttonAction:(UIButton*)sender
{
[self touchCancel:sender];
/* DO SOME MORE ACTIONS */
}
-(void)changeColor:(UIButton*)sender
{
sender.backgroundColor = [UIColor redColor];
}
-(void)touchCancel:(UIButton*)sender
{
sender.backgroundColor = [UIColor clearColor];
}
If you want to make the button have a different selected color, create an array that holds all the selected states. Then use the array to check if the button color needs a different color in cellForRowAtIndexPath.
When you want to change the button color just change the value in the array and call
[self.tableView reloadData];
Be sure to do it outside the if (cell == nil) method so it is also called when the cell is reused.