How to get other control value from UITableViewCell? - iphone

I have one doubt that how to get other control's value when we select a row or tap on button while having custom tableViewCell.
Suppose I have a TableView Cell with a TextField, a Slider and button. Button has action using:
btn.tag = indexPath.row;
[btn addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
Now I can get button on its action method. I need to get textField's value and slider's value on button tap.
The one option is I create a array and store values for these two control in that array and manage this. But I don't think this is correct way to manage it.
Please navigate me to the currect way to get value of UITableViewCell's subview's value.
Thanks

While creating your textfield and slider, give them a constant tag and then add to cell's contentView
textfield.tag= TEXTFIELDTAG; //TEXTFIELDTAG = 100 or any other constant
[cell.contentView addSubview:textfield];
and then in your buttonTapped: method
-(void)buttonTapped:(id)sender
{
int row = ((UIButton*)sender).tag;
NSIndexPath* indexpath = [NSIndexPath indexPathForRow:row inSection:0]; // in case this row in in your first section
UITableViewCell* cell = [table cellForRowAtIndexPath:indexPath];
UITextField* textfield = [cell.contentView viewWithTag:TEXTFIELDTAG];
}

Whenever you create subviews (button , text field etc. ) for your UITableViewCell don't forget to tagged them.
myTextField.tag = 0;
myTextLabel.tag = 1;
[cell addSubview:myTextField];
[cell addSubview:myTextLabel];
Once you tagged, you could access them using below method.
- (UIView *)viewWithTag:(NSInteger)tag
When you select,you could get the subviews of your UITableViewCell's by using ViewWithTag function of UIView.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableview cellForRowAtIndexPath:indexPath];
UITextField* myTextField = [cell viewWithTag:0];
UILabel* myTextLabel = [cell viewWithTag:1];
}

Related

I have a drawer of buttons in UITableViewCell. How do I get the indexPath of the cell and delete it?

I have implemented this button drawer and I've added some buttons to it. That said, I'm unsure how I'll go about sending messages from these buttons in the drawer to the appropriate delegate method to delete the item from my tableView.
How do I get the correct indexPath? Should I make a new NSIndex for uitableviewcells that have had their check button toggled?
Thanks
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
HHPanningTableViewCell *cell = (HHPanningTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSInteger directionMask = indexPath.row % 5;
if (cell == nil) {
cell = [[HHPanningTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UIView *drawerView = [[UIView alloc] initWithFrame:cell.frame];
drawerView.backgroundColor = [UIColor grayColor];
cell.drawerView = drawerView;
UIImage *checkImage = [UIImage imageNamed:#"check.png"];
UIButton *checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
[checkButton setImage:checkImage forState:UIControlStateNormal];
cell.frame = CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height);
checkButton.frame = CGRectMake(10, 10, checkImage.size.width, checkImage.size.height);
[drawerView addSubview:checkButton];
[checkButton addTarget:nil action:#selector(onCheckMarkTap:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)onCheckMarkTap {
NSLog(#"Delete the cell");
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
}
}
This question already has an answer. You get the coordinates of the button that was tapped in the table view's coordinate system using target/action with an event or via a gesture recognizer, then use UITableView's method -indexPathForRowAtPoint: to get the indexPath of the cell containing the button at that point.
Within cellForRowAtIndexPath:
checkButton.tag = indexPath.row
Also inside onCheckMarkTap, do this:
- (void)onCheckMarkTap : (id) sender
{
if (sender.tag == 0)
///code
else if (sender.tag == 1)
///code
}
The way I handle problems like this in my own code is to subclass "UIButton", where I add in a "NSIndexPath" or "tableRow" ivar into the subclassed button. Let's name is "StangButton".
With a subclassed button, you can populate the "indexPath" ivar when you are composing the cell via "cellForRowAtIndexPath:".
Then, when the button is pressed, you'll know which button was pressed and which row it was in.
You can also check to see if the "tableView:didSelectRowAtIndexPath:" table view delegate method is called when the button is touched in the cell.

Change background color of the button in UITableViewCell based on selection

I have a UITableView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Where we configure the cell in each row
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
self.myButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.myButton.tag = 5;
self.myButton.frame = CGRectMake(190.0f, 5.0f, 70.0f, 25.0f);
self.myButton.layer.borderColor = [UIColor blackColor].CGColor;
self.myButton.layer.borderWidth = 0.5f;
self.myButton.backgroundColor = [UIColor grayColor];
[self.myButton setTitle:#"Set Active" forState:UIControlStateNormal];
[self.myButton addTarget:self action:#selector(myButton:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview: self.myButton];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
-(void) myButton:(id)sender{
[sender setBackgroundColor:[UIColor redColor]];
}
Assume, there 3 rows in the tableview section. I have the button in 3 rows.
At the first instance, the button in the first row should have red color and the other 2 rows should have gray color.
If I select the button in the 2nd row, then the button in the 2nd row should be red and the other 2 gray and so on. I haven't figured out a way to do it. Any suggestions?
I am able to change the color of the button I have selected from cell. But at the same instance, the previously selected button and all the other buttons(except the selected button) should be default color. At a time only one button will be highlighted, and that will always be the selected button at that instance.
I think the right way to do this - subclass UITableViewCell and declare own protocol that will inform delegate in which cell button was pressed, and in the delegate - loop through all cells and set default color for all and red color for selected.
I made demo project
Easy way is set different tag for each button. Like this:
button.tag = indexPath.row + c;
when 'c' is constant.
And in you method:
-(void) myButton:(id)sender{
for( int i=0; i<numberOfRowsInTable; ++i )
[(UIButton *)[self.view viewForTag:i+c] setBackgroundColor:[UIColor grayColor]];
[(UIButton *)sender setBackgroundColor:[UIColor redColor]];
}
But if you have 2 or more section in table this way may be not work
Take a look at this: How can I loop through UITableView's cells?
Loop through the cells and set the "inactive" buttons to gray.
Just try this code:
-(void) myButton:(id)sender{
NSLog(#"sender Tag=== %d",[sender tag]);
UIButton *btn=(UIButton *)sender;
[btn setBackgroundColor:[UIColor redColor ]];
}

adjusting UITableView's cell at runtime

I have subclassed a UITableViewCell. What I want to have is when I click on the cell, I added a UIView to the bottom of the cell and adjust the height of the cell accordingly. Here's my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell* cell = (MyCell *) [self.table cellForRowAtIndexPath:indexPath];
UIView * options = [[UIView alloc] initWithFrame:CGRectMake(0, cell.frame.size.height - 27, cell.frame.size.width, 27)];
UIButton* button1 = [UIButton buttonWithType:UIButtonTypeCustom];
[options addSubview:button1];
UIButton* button2 = [UIButton buttonWithType:UIButtonTypeCustom];
[options addSubview:button2];
UIButton* button3 = [UIButton buttonWithType:UIButtonTypeCustom];
[options addSubview:button3];
//did some layout calculation here to position the button
[cell addSubview:options];
}
Here's a video that illustrates the issue
Also I've tried to change the accessoryView of my cell from my custom UIButton to the regular UITableViewCellAccessoryDisclosure but it didn't work
MyCell * cell = (MyCell *)[self.table cellForRowAtIndexPath:temp];
[cell.accessoryView removeFromSuperview];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
If you're curious what I am trying to do, I am trying to create a tweetbot uitableviewcell, where you press the cell/row and it presents you with other options (retweets, etc) and also it was shown animated.
I don't know if I correctly understand what you are trying to do. But if you do want to animate the change of the UITableViewCell's height try to adjust it within - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath and call
[tableView beginUpdates];
[tableView endUpdates];
Put controls into another cell and use
insertRowsAtIndexPaths:withRowAnimation:
to show it and
deleteRowsAtIndexPaths:withRowAnimation:
to hide it.

UIButton Event for Delete Row in UITableView

I add button in UITableView cell. My code is
UIButton *btnView = [[UIButton buttonWithType:UIButtonTypeContactAdd] retain];
btnView.frame = CGRectMake(280.0, 8.0, 25.0, 25.0);
//[btnView setImage:[UIImage imageNamed:#"invite.png"] forState:UIControlStateNormal];
[btnView addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:btnView];
[btnView release];
My button action is
- (void)action:(id)sender
{
}
I want to know, how to get current table row index when click. I want to delete table row when click on button.
Edit::
I found a way for delete with animation
[listOfItems removeObjectAtIndex:indexPath.row];
[self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
I believe one approach is to store the row number in the button tag
btnView.tag = [indexPath row]
in the action
- (void)action:(id)sender
{
UIButton * btn = (UIButton)sender;
int row = btn.tag;
}
I usually use this method:
- (IBAction)buttonAction:(id)sender {
UIButton *button = sender;
UIView *contentView = [button superview];
UITableViewCell *cell = (UITableViewCell *)[contentView superview];
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
//Do something
}
Depending on the layout of your UITableViewCell it is possible that you have to traverse deeper into your TableViewCell Views.
http://nshipster.com/associated-objects/ Use an associated object of a NSNumber surrounding the row or the index path itself as the associated object
//when you create the button
objc_setAssociatedObject(button, associationKeyForButton, [NSNumber numberWithInteger:indexPath.row], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//in the touch up inside handler to get the row back.
NSNumber* rowNumber = objc_getAssociatedObject(sender, associationKeyForButton);

iPhone question: How can I add a button to a tableview cell?

Little background, the table view is filled by a fetchedResultsController which fills the table view with Strings. Now I'm trying to add a button next to each String in each tableview cell. So far, I've been trying to create a button in my configureCell:atIndexPath method and then add that button as a subview to the table cell's content view, but for some reason the buttons do not show up. Below is the relevant code. If anyone wants more code posted, just ask and I'll put up whatever you want. Any help is greatly appreciated.
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// get object that has the string that will be put in the table cell
Task *task = [fetchedResultsController objectAtIndexPath:indexPath];
//make button
UIButton *button = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[button setTitle:#"Check" forState:UIControlStateNormal];
[button setTitle:#"Checked" forState:UIControlStateHighlighted];
//set the table cell text equal to the object's property
cell.textLabel.text = [task taskName];
//addbutton as a subview
[cell.contentView addSubview:button];
}
- (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] autorelease];
}
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
Three comments:
You'll probably need to set the frame of your UIButton. Otherwise it doesn't know how big it's supposed to be and where it's supposed to be placed. It's possible that it comes with a default frame, but I haven't investigated that.
You're leaking your buttons. You don't need to retain after calling [UIButton buttonWithType:...];
You have the possibility of adding multiple buttons to the same cell. If you're reusing a cell, then you should first invoke removeFromSuperview each subview of cell.contentView .