I want to create a simple checkbox in a tableview. First I create the View in the storyboard and every element get a tag in the cell. Then I coded this in Controller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
UIButton *checkbox = (UIButton *)[cell viewWithTag:103];
checkbox.selected = NO;
[checkbox setBackgroundImage:[UIImage imageNamed:#"uCheckbox2px"] forState:UIControlStateNormal];
[checkbox addTarget:self action:#selector(changeState:) forControlEvents:UIControlEventTouchUpInside];
...
}
-(void) changeState:(UIButton *)checkbox
{
checkbox.selected = !checkbox.selected;
if (checkbox.selected)
[checkbox setBackgroundImage:[UIImage imageNamed:#"cCheckbox2px"] forState:UIControlStateSelected];
else
[checkbox setBackgroundImage:[UIImage imageNamed:#"uCheckbox2px"] forState:UIControlStateNormal];
}
But if I tap on the button the image don't change. Why is this and how I fix it?
Thanks for help!
This is because everytime calling cellForRowAtIndexPath: checkbox.selected = NO; will make the selected property FALSE. So after that, in the changeState:,
checkbox.selected = !checkbox.selected;
will change the selected property to TRUE. So whenever you tap the button, selected property becomes TRUE only. So move checkbox.selected = NO; to inside of if(cell == nil) condition
Make it like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
UIButton *checkbox = (UIButton *)[cell viewWithTag:103];
[checkbox setBackgroundImage:[UIImage imageNamed:#"uCheckbox2px"] forState:UIControlStateNormal];
[checkbox setBackgroundImage:[UIImage imageNamed:#"cCheckbox2px"] forState:UIControlStateSelected];
[checkbox addTarget:self action:#selector(changeState:) forControlEvents:UIControlEventTouchUpInside];
...
}
-(void) changeState:(UIButton *)checkbox
{
checkbox.selected = !checkbox.selected;
}
I guess the code you have given in your button tap event is not needed. Only changing the state is enough.
if (checkbox.selected)
[checkbox setBackgroundImage:[UIImage imageNamed:#"cCheckbox2px"] forState:UIControlStateSelected];
else
[checkbox setBackgroundImage:[UIImage imageNamed:#"uCheckbox2px"] forState:UIControlStateNormal];
But you need to specify the image for both states (UIControlStateSelected and UIControlStateNormal) in your cellForRowAtIndexPath.
Related
In my cell have 1 button.
I want to change button title when I click.
Exp: default title: Play
When I click button the first it will handle event1, and change title to Stop.
When I click the second, it will change title to Play and handle event2.
...
Understand me? And remember that: button in tableView Cell.
Please help me!
Try this
In your cellForRowAtIndexPath
UIButton *button = [[UIButton alloc]initWithFrame:Your Frame];
[button addTarget:self action:#selector(ButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
Button.tag = indexPath.row;
[cell.contentView addSubview:Button];
Then write ButtonClicked method
-(void)ButtonClicked:(UIButton*)button{
if (button.tag == 0)
{
//Here button at 0th row is selected.
//Write your code here
}
}
Hope it helps.
Here is Objective-C version:
- (void) playPauseAction:(id)sender {
UIButton *button = (UIButton *)sender;
if ([button.currentTitle isEqualToString:#"Play"]) {
[button setTitle:#"Pause" forState:UIControlStateNormal];
// Playing code
} else {
[button setTitle:#"Play" forState:UIControlStateNormal];
// Pausing code
}
}
1) In your cellForRowAtIndexPath: method, assign button tag as index:
cell.yourbutton.tag = indexPath.row;
2) Add target and action for your button as below:
[cell.yourbutton addTarget:self action:#selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
3) Code actions based on index as below in ViewControler:
-(void)yourButtonClicked:(UIButton*)sender
{
Bool cicked=1;
if(clicked)
{
[cell.yourbutton setTitle: #"myTitle" forState:#""];
}
}
you can try these way......
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
tags = (int)indexPath.row;
[tblname reloadData];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier"
............
............
............
if (indexpath.row == tags){
[cell.btnName setTitle:#"Newtitle" forState:UIControlStateSelected];
}else{
[cell.btnName setTitle:#"OldTitle" forState:UIControlStateNoramal];
}
}
1.Add TargetAction to the button as
[btn addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
2.Just follow action method like this
-(void)buttonClicked:(UIButton*)btn
{
if ([btn.titleLabel.text isEqualToString:#"Play"]) {
[btn setTitle:#"Stop" forState:UIControlStateNormal];
}else{
[btn setTitle:#"Play" forState:UIControlStateNormal];
}
}
Following is a code fragment from cellForRowAtIndexPath. I have added 2 buttons on a Cell.
When the user clicks on Button A the image of Button A should be a.png. And Button B should change to default.png.
When the user clicks on Button B the image of Button B should be b.png. And Button A should change to default.png.
How can i do this ?
cellForRowAtIndexPath Method
[cell.aButton addTarget:self action:#selector(methodA:) forControlEvents:UIControlEventTouchUpInside];
[cell.bButton addTarget:self action:#selector(methodB:) forControlEvents:UIControlEventTouchUpInside];
- (void) methodA:(id) sender {
[((UIButton *)sender) setImage:[UIImage imageNamed:#"a.png"] forState:UIControlStateSelected];
// How to change the image of Button B to default.png ??
}
- (void) methodB:(id) sender {
[((UIButton *)sender) setImage:[UIImage imageNamed:#"b.png"] forState:UIControlStateSelected];
// How to change the image of Button A to default.png ??
}
If you have set tag to your buttons like aButton has tag= 1, and bButton has tag= 2
- (void) methodB:(id) sender {
UIButton *bButton =((UIButton *)sender) ;
[bButton setImage:[UIImage imageNamed:#"b.png"] forState:UIControlStateSelected];
UIButton *aButton = (UIButton *)[bButton.superview viewWithTag:bButton.tag-1];
[aButton setImage:[UIImage imageNamed:#"default.png"] forState:UIControlStateSelected];
}
- (void) methodA:(id) sender {
UIButton *aButton =((UIButton *)sender) ;
[aButton setImage:[UIImage imageNamed:#"a.png"] forState:UIControlStateSelected];
UIButton *bButton = (UIButton *)[bButton.superview viewWithTag:aButton.tag+1]; //updated here, instead of bButton, put aButton
[bButton setImage:[UIImage imageNamed:#"default.png"] forState:UIControlStateSelected];
}
Enjoy Coding !!
Try this,
- (void) methodA:(id) sender {
UIButton *buttonA = (UIButton *)sender;
CGPoint pointInTable = [field convertPoint:buttonA.bounds.origin toView:_tableView];
NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:pointInTable];
UITableViewCell *cell = [_tableView cellForRowAtIndexPath:nowIndex];
//now access the button and change button images
//cell.aButton setImage:
//cell.bButton setImage:
}
Do the same for button B action.
Note: I recommend using custom tableview cell and handling this button actions inside the custom cell.
For both the buttons, set a.png and default.png for UIControlStateNormal and UIControlStateSelected respectively
Now you can simply make the button selected and deselected accordingly and donot worry about the image.
Hope this image gives you another hint.
To handle your selection issue, the best way is to handle it in your tableViewCell class, where you can access both the buttons and write a delegate or callback if required.
Try this...
cellForRowAtIndexPath
[cell.aButton addTarget:self action:#selector(methodToggle:) forControlEvents:UIControlEventTouchUpInside];
[cell.bButton addTarget:self action:#selector(methodToggle:) forControlEvents:UIControlEventTouchUpInside];
[cell.aButton setImage:[UIImage imageNamed:#"default.png"] forState:UIControlStateNormal];
[cell.bButton setImage:[UIImage imageNamed:#"default.png"] forState:UIControlStateNormal];
[cell.aButton setImage:[UIImage imageNamed:#"a.png"] forState:UIControlStateSelected];
[cell.bButton setImage:[UIImage imageNamed:#"b.png"] forState:UIControlStateSelected];
cell.aButton.tag == 111;
cell.aButton.tag == 222;
Just One method for both Buttons
- (void) methodToggle:(id) sender {
UIButton * btn = (UIButton *)sender;
if (btn.tag == 111)
{
UIButton * btnAnother = (UIButton *)[[btn superview] viewWithTag:222];
btnAnother.selected = NO;
}
if (btn.tag == 222)
{
UIButton * btnAnother = (UIButton *)[[btn superview] viewWithTag:111];
btnAnother.selected = NO;
}
btn.selected = YES;
}
Inside tableView:cellForRowAtIndexPath: add following code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
[cell.aButton setTag:1];
[cell.aButton addTarget:self action:#selector(methodA:) forControlEvents:UIControlEventTouchUpInside];
[cell.aButton setTag:2];
[cell.bButton addTarget:self action:#selector(methodB:) forControlEvents:UIControlEventTouchUpInside];
}
Implement the button event handlers as-
- (void) methodA:(id) sender
{
UIView *view = [sender superView];
UIButton *senderButton = (UIButton *)sender;
[senderButton setImage:[UIImage imageNamed:#"a.png"] forState:UIControlStateSelected];
UIButton *otherButton = [view viewWithTag:2];
[otherButton setImage:[UIImage imageNamed:#"default.png"] forState:UIControlStateNormal];
}
- (void) methodB:(id) sender
{
UIView * view = [sender superView];
UIButton *senderButton = (UIButton *)sender;
[senderButton setImage:[UIImage imageNamed:#"b.png"] forState:UIControlStateSelected];
UIButton *otherButton = [view viewWithTag:1];
[otherButton setImage:[UIImage imageNamed:#"default.png"] forState:UIControlStateNormal];
}
Write a CustomCell class which has 2 buttons with target methods and delegate method to notify the table view when buttons clicked. Use this cell in the table view.
In target methods do the image changes(A/B) and fire the delegate method to notify the tableViewController.
You can keep indexpath as a property of cell and pass it with the delegate to tableView.(Set the indexpath for the cell in tableView's cellForRowAtIndexPath:)Then you can identify which cell's button was clicked and relevant data object can fetch from your data source.
CustomCell.m
- (IBAction)onButtonAClicked:(id)sender {
// change your images
[delegate cellButtonClicked:self.indexpath];
}
TableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
cell.delegate = self;
}
cell.indexpath = indexPath;
}
//delegate method
-(void)cellButtonClicked:(NSIndexPath *)indexPath{
//get the related data object for the cell using indexPath from your data source
}
i m having a simple section table view. I have added a button at the left side of image.This button is selectable.Only one button (each cell have single button of same type) can be selected at a time and selected button background image changes to a specific selected image, others button back ground image changes to deselect image.If you tap again on selected image it remains selected.
How ever i am not getting correct behaviour.
code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// UITableViewCell *cell=nil;
CustomCellMasterCustomer *cell=nil;
static NSString *cellIdentifier=#"Locations";
Customer *mCustomer;
cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell==nil){
// cell=[self reusableContentWithIdentifier:cellIdentifier];
cell=(CustomCellMasterCustomer *)[self reusableContentWithIdentifier:cellIdentifier];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = indexPath;
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageDisabled.png"] forState:UIControlStateNormal];
[button setFrame:CGRectMake(10, 5, 36, 30)];
[button addTarget:self action:#selector(viewDetail:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
cell.aCustomer = mCustomer;//alok added
if (indexPath == self.mPreviousIndex)
{
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];
}
else
{
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageDisabled.png"] forState:UIControlStateNormal];
}
return cell;
}
-(void)viewDetail:(id)sender
{
CGPoint buttonOrigin = [sender frame].origin;
// this converts the coordinate system of the origin from the button's superview to the table view's coordinate system.
CGPoint originInTableView = [self.allCustomerTable convertPoint:buttonOrigin fromView:[sender superview]];
// gets the row corresponding to the converted point
NSIndexPath *rowIndexPath = [self.allCustomerTable indexPathForRowAtPoint:originInTableView];
CustomCellMasterCustomer *cell = (CustomCellMasterCustomer *)[self.allCustomerTable cellForRowAtIndexPath:rowIndexPath];
[self fillDetailViewWithCustomerInformation:cell.aCustomer];
//change button background image
UIButton *btn = (UIButton *)sender;
[btn setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];
self.mPreviousIndex = rowIndexPath;
[self.allCustomerTable reloadData];
}
what wrong i am doing,
any suggestion
Try this. Because indexpath always recreate with same row and section number. It won't same as previous.
if (indexPath.row == self.mPreviousIndex.row && indexPath.section == self.mPreviousIndex.section)
{
[button setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];
}
And this two line of code, not needed anymore
/* UIButton *btn = (UIButton *)sender;
[btn setBackgroundImage:[UIImage imageNamed:#"cellLeftImageEnabled.png"] forState:UIControlStateNormal];*/
You should not add a button out side the if block. In UITableView cells will be reused, if the cell is reused and at already has a button added to contentView then you should not add one more on top of it. so create a custom cell and make the buttion instance visible outside the class by declaring the buttion property in customCell.h. Now check the condition -
if (selected)
{
cell.button.backgroundImage = selectedImage;
}
else
{
cell.button.backgroundImage = unselectedImage;
}
I have 1 UITableView has multiple UIButton (named is "Open"button with different tags) in each row, i set tag for them. Now, after click on any button in each row, it'll show a UIView (detailView). On detailView has 1 "Submit"button. I want to when user click on "Submit" button, "Open"button with tag selected is disable. How can i do that? I used this code :
Code to create tableview with mutiple "Open"button:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%d,%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UIButton *market = [UIButton buttonWithType:UIButtonTypeCustom];
[market addTarget:self action:#selector(marketPressedAction:) forControlEvents:UIControlEventTouchDown];
[market setTag:3000];
[market setFrame:CGRectMake(200, 6, 30, 30)];
[cell.contentView addSubview:market];
}
marketButton = (UIButton *)[cell.contentView viewWithTag:3000];
[marketButton setTag:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
_tableView.contentInset = UIEdgeInsetsMake(0, 0, 100, 0);
return cell;
}
And code when click on"Open"button:
- (void)marketPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
buttontag = button.tag;
NSLog(#"Market button click at row %d",buttontag);
if ([sender isSelected]) {
[sender setImage:[UIImage imageNamed:#"Marketplace.png"] forState:UIControlStateHighlighted];
[sender setSelected:NO];
}
else {
[sender setImage:[UIImage imageNamed:#"MarketplaceSelect.png"] forState:UIControlStateSelected];
[sender setSelected:YES];
}
}
}
If you want your "Open" button to be disabled after you click submit button, you should use delegates
UIButton *btn = (UIButton *)sender;
btn.enabled = NO;
Try this one in button click method
EDITED :
Change you marketPressedAction parameter id to UIButton * and write code of below
-(void)marketPressedAction:(UIButton *)sender
{
[sender setImage:[UIImage imageNamed:#"Marketplace.png"] forState:UIControlStateHighlighted];
[sender setImage:[UIImage imageNamed:#"MarketplaceSelect.png"] forState:UIControlStateSelected];
/// Here set you image ////////////////
[sender setImage:[UIImage imageNamed:#"myCustome.png"] forState:UIControlStateNormal];
[self createMarketPlaceForm]; // call detailView
sender.enabled = NO;
sender.userInteractionEnabled = NO;
}
In my application I load a tableView with an array and I've added an UIButton to each row as subView for my need. I know that the reused cell will have the added button So keeping this fact in mind I've Implemented the -cellForRowAtIndexPath method like below
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"surgeon"];
if (!cell) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"surgeon"];
}
[[cell.contentView subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
//before adding button to the contentView I've removed allSubViews
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(142, 4, 28, 28)];
[btn setImage:[UIImage imageNamed:[NSString stringWithFormat:#"infoicon.png"]] forState:UIControlStateSelected];
[btn setSelected:YES];
[btn addTarget:self action:#selector(checkbtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[btn setTag:indexPath.row];
if (indexPath.row==1) {
NSLog(#"CELL %# CONTNTVEW %#",cell.subviews,cell.contentView.subviews);
}
[cell.contentView addSubview:btn];
return cell;
}
My problem is that the TableView is loaded well at first time But when I scroll the TableView the Button I have added is Removed even though the removing of subView is done before adding the Button as subView help me to get This work
It appears that removing all of the subviews of the cell's content view is causing the cell to re-create its cell content when you set the text. I've managed to reproduce the problem, and fixed it by using this method instead:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"surgeon"];
if (!cell) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"surgeon"];
}
for(UIView *subview in cell.contentView.subviews)
{
if([subview isKindOfClass: [UIButton class]])
{
[subview removeFromSuperview];
}
}
//before adding button to the contentView I've removed allSubViews
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(142, 4, 28, 28)];
[btn setImage:[UIImage imageNamed:[NSString stringWithFormat:#"infoicon.png"]] forState:UIControlStateSelected];
[btn setSelected:YES];
[btn addTarget:self action:#selector(checkbtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[btn setTag:indexPath.row];
if (indexPath.row==1) {
NSLog(#"CELL %# CONTNTVEW %#",cell.subviews,cell.contentView.subviews);
}
cell.textLabel.font=[UIFont systemFontOfSize:12];
cell.textLabel.text=#"A surgeon.";
[cell.contentView addSubview:btn];
return cell;
}
Important note: if you plan on doing any further cell customization, you'll need to remove them manually in the loop as well.