Three state UIButton in ios TableView List - ios

I have students attendance list in UITableView. Where each cell having an UIButton to set student attendance like Present, Absent and Leave on button click. How can I achieve this on single button.

You can do this by simply implementing the following #selector for your UIButton in UITableViewCell.
- (void)btnSetMode:(id)sender
{
UIButton *btn = (UIButton *)sender;
if (btn.tag == 0)
{
[btn setTitle:#"Present" forState:UIControlStateNormal];
btn.tag = 1;
// Define your required task...
}
else if (btn.tag == 1)
{
[btn setTitle:#"Absent" forState:UIControlStateNormal];
btn.tag = 2;
// Define your required task...
}
else if (btn.tag == 2)
{
[btn setTitle:#"Leave" forState:UIControlStateNormal];
btn.tag = 3;
// Define your required task...
}
else if (btn.tag == 3)
{
[btn setTitle:#"Attendance" forState:UIControlStateNormal];
btn.tag = 0;
// Define your required task...
}
}
Your single button will do all the required task as you wanted.

If you have An UIButton in your tableViewCell then add Target to your UIButton and set button Tag with indexPath.row in cellForRowAtIndexPath like-
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
attendanceListTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.studentNameLbl.text=[NSString stringWithFormat:#"Student %ld",(long)indexPath.row];
cell.editBtn.tag=indexPath.row;
[cell.editBtn setTitle:[attandanceArry objectAtIndex:indexPath.row] forState:UIControlStateNormal];
[cell.editBtn addTarget:self action:#selector(editAttendance:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(void)editAttendance:(id)sender{
UIButton *btn=(UIButton*)sender;
if ([btn.titleLabel.text isEqualToString:#"P"]) {
[btn setTitle:#"A" forState:UIControlStateNormal];
[attandanceArry replaceObjectAtIndex:btn.tag withObject:#"A"];
}else if ([btn.titleLabel.text isEqualToString:#"A"]) {
[btn setTitle:#"L" forState:UIControlStateNormal];
[attandanceArry replaceObjectAtIndex:btn.tag withObject:#"L"];
}else if ([btn.titleLabel.text isEqualToString:#"L"]) {
[btn setTitle:#"P" forState:UIControlStateNormal];
[attandanceArry replaceObjectAtIndex:btn.tag withObject:#"P"];
}
}
In this attandanceArry is mutableArray having all default value is "P" with capacity of your number of students and editBtn is your cell UIButton. Here I use custom tableViewCell class i.e. attendanceListTableViewCell class having UIButton. At the end you can use attandanceArry as result array when you complete editing attendance. I hope this will help you...:)

Change the button title and background color when it's clicked. Personally, I would use three different buttons so that all different options would be visible at the same time. UIPicker is one option too.

Is a UISegmentedControl what you are looking for?
See the Apple Documentation here. It can be configured in a storyboard with the correct number of segments and segment titles. When the user selects a segment it will be highlighted, and any other segments are deselected.

Related

Only One RadioButton is Selectable for a Column Group in UITableView

Before asking this question I googled a lot but not able to find suitable answer.
I'm have a UITableView with n number of Columns. The thing is the Column is Grouped according to a key. So my UITableView header is splitted into two, one for the column group and and this column group is divided to show columns.
I have created a custom class for the cell there I display radio button in each column.
Code:
In cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GridTableViewCell *cell = nil; // My custom class for cell
CGFloat startX = 230;
if (cell == nil)
{
cell = [[GridTableViewCell alloc] initWithStyle1:UITableViewCellStyleDefault reuseIdentifier:#"Cell" withRows:[self.rowHeaderArray objectAtIndex:indexPath.row]];
for (int i = 0; i < [self.groupColumNmeArray count]; i++) { // groupColumNmeArray contains the Column Group name
NSArray *values = [_subColumnDict objectForKey:[self.groupColumNmeArray objectAtIndex:i]]; // subColumnDict contains the value for each column
self.originalDataArray = [CustomTableHeaderParser parseColumnInfo:values];// Parsing the values array for getting column name, type, width etc
for (CustomTableColumn *column in self.originalDataArray)
{
switch (column.columnType) // acc. to column type display the cell with values.
{
case RadioBtn:
{
_btTemp = [[UIButton alloc]initWithFrame:CGRectMake(startX, 2, subCellWidth , 40)];
[_btTemp setTag:indexPath.row];//indexPath.row];
[_btTemp addTarget:self action:#selector(radioButtonsClicked:) forControlEvents:UIControlEventTouchUpInside];
[_btTemp setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
[_btTemp setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_btTemp.titleLabel.font =[UIFont systemFontOfSize:14.f];
[self.radioButtons addObject:_btTemp];
[cell addSubview:_btTemp];
}
break;
startX += 2+subCellWidth;
}
}
}
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.frame];
cell.selectedBackgroundView.opaque = YES;
return cell;
}
Radio button click action method;
-(IBAction) radioButtonsClicked:(UIButton *) sender {
if ([sender isSelected]) {
[sender setSelected: NO];
[sender setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
} else {
[sender setSelected: YES];
[sender setImage:[UIImage imageNamed:#"radio-on.png"] forState:UIControlStateNormal];
}
NSLog(#"BUTTON TAG %ld",(long)sender.tag);
}
So I'm able to make selections for radio buttons in all column but actually what I want is For each column group only one radio button is selectable.
Can anybody help me. Any help would be greatly appreciable.
You can set other button's selection status as following
-(IBAction) radioButtonsClicked:(UIButton *) sender {
sender.selected = !sender.selected;
for (UIView *vw in sender.superview.subviews)
{
if([vw isKindOfClass:[UIButton class]] && vw != sender)
{
UIButton *otherBtn = (UIButton*)vw;
otherBtn.selected = NO;
}
}
}
for setting button Image - on/off, write that code at the time of creating button in cellforrow..
[_btTemp setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
[_btTemp setImage:[UIImage imageNamed:#"radio-on.png"] forState:UIControlStateSelected];

IOS handle event click button in tableView cell

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];
}
}

radio button in tableviewcell for each section - ios

my tableview containing two sections , each section contains n numbe of rows, in which my 1st row of each section dont have radio button. i am finding difficulty to program a group of selected radio button.
in this example , "prison break" and "homeland" are my sections. this section contains 6 rows. only 4 rows are having radio button , i need to toggle between these two correspondingly.
i have tried with creating all radiobutton array in cellForRowAtIndexPath: and in add target for each button , i am deselecting all others.
-(IBAction)toggleButton:(UIButton *)button{
//select the tapped radio button.
button.selected = !button.selected;
// Unselect all others.
for (id key in _myButtonDict) {
UIButton *btn = [_myButtonDict valueForKey:key];
NSLog(#"%ld",(long)btn.tag);
if ([_myButtonDict valueForKey:key] != button) {
[[_myButtonDict valueForKey:key] setSelected:NO];
}
} }
#interface RadioButton : UIButton
#property (nonatomic,assign) NSInteger *row;
#property (nonatomic,assign) NSInteger *section;
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//create a tableviewcell
//add the radio button to each cell.
RadioButton *radioButton = [RadioButton buttonWithType:UIButtonTypeCustom];
[radioButton setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
[radioButton setImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateSelected];
//radiobutton properties.
radioButton.tag = indexPath.section;
radioButton.row = indexPath.row;
[radioButton addTarget:self action:#selector(toggleButton:) forControlEvents:UIControlEventTouchUpInside];
cell.accessoryView = radioButton;
return cell;
}

Maintain state of custom button in UITableview cell when scrolls

I know this question is very similar to other questions, but i doesn't resolve the problem using that approach.i follow most of the available solution but it doesn't work for me..
I know that when tableview scrolls it reuse cell but i doesn't know the approach of maintaining the button state . i'll try with following link
How to use Reusable Cells in uitableview for IOS
IOS: Maintaining button state in uitableviewcell
How to Handle Favourite button clicks in custom Tableview cells iOS?
I done all the things.use tags, use touch points and all but nothing seems to work for me.so help me out..and here is my sample code
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
/*
* Set button for cell to subscribe with it
*/
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;
[cell.btnsubscribe addTarget:self action:#selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
if (![_arraybtnState containsObject:listid] )
{
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:YES];
}
else {
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:NO];
}
return cell;
}
_arrbtnstate contains the ids that user follows.
and listid contains unique id comes from database too
And the click event method...
- (IBAction)clickBtnSubscribe:(id)sender {
UIButton *button = (UIButton*)sender;
NSLog(#"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
if (button.selected) {
[self.arraybtnState addObject:tagnum];
[button setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
NSLog(#"Subscribe");
[self subscribeButton:button.tag];
[button setSelected:NO];
}
else
{
[self.arraybtnState removeObject:tagnum];
[button setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
NSLog(#"unsubscribe");
[self unsubscribeButton:button.tag];
[button setSelected:YES];
}
}
Note: In this code, button is created in storyboard.,but i'll also tried without storyboard too.
First of all this line cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303]; is to be changed. Follow the below steps and try
in custom subcategoryCell connect IBOutlet to btnsubscribe.
in storyboard, you can set both selected and not normal images to a UIButton, here it is btnsubscribe. If you find it difficult follow this
in cellForRowAtIndexPath: remove below lines
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
update the following lines
if (![_arraybtnState containsObject:listid] )
{
[cell.btnsubscribe setSelected:YES];
}
else {
[cell.btnsubscribe setSelected:NO];
}
or simply [cell.btnsubscribe setSelected:(![_arraybtnState containsObject:listid] )];
Keep the addTarget in cell for row method (since you have custom cell class, it is better to move the button action to cell class and pass the result to viewcontroller by callback or delegate. not discussing that now but recomments) and update the clickBtnSubscribe: by removing
[button setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
these lines. assumes other parts are working properly.
You are setting Selected and unselected image for button's Normal state in both cases i.e UIControlStateNormal.
When you are using selected method you do not require to setImage again. Just set Image for Normal and selected state for button properly in cellForRowAtIndexpath or in xib. You are done.
First remove the setting image in clickBtnSubscribe:() method.
Now in your storyboard set images for Normal and selected state.
Also remove set Image in cell for row at indexpath as you have already done in view.
You can maintain the state of the buttons as-
// initialize your array only once
_arraybtnState = [[NSMutableArray alloc] init];
// cell for row at index path would be
//initially each cell will have follow image
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
[cell.btnsubscribe setTag: indexPath.row];
[cell.btnsubscribe addTarget:self action:#selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] )
{
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:YES];
}
else
{
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
[cell.btnsubscribe setSelected:NO];
}
return cell;
}
- (IBAction)clickBtnSubscribe:(id)sender {
UIButton *button = (UIButton*)sender;
NSLog(#"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
if (button.selected) {
[self.arraybtnState addObject:tagnum];
NSLog(#"Subscribe");
[self subscribeButton:button.tag];
[button setSelected:NO];
}
else
{
[self.arraybtnState removeObject:tagnum];
NSLog(#"unsubscribe");
[self unsubscribeButton:button.tag];
[button setSelected:YES];
}
//after doing modification update the respective row as
UIButton *button = (UIButton *)sender;
// Find Point in Superview
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
// Infer Index Path
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInSuperview];
//relaod the row
NSArray* indexPathModel = [NSArray arrayWithObjects:indexPath, nil];
[self.tableView reloadRowsAtIndexPaths: indexPathModel withRowAnimation:UITableViewRowAnimationNone];
}
reloading row will reflect the changes done in the modal to the UI.
I think you can put this line in viewDidLoad or after you load what all have subscribed .
_arraybtnState = [NSMutableArray arrayWithArray:[self.strSubscribe componentsSeparatedByString:#","]];
Then the cellForRowAtIndexPath will loook like below
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];
/*
* Set button for cell to subscribe with it
*/
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;
[cell.btnsubscribe addTarget:self action:#selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];
if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] ) {
[cell.btnsubscribe setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
}
else {
[cell.btnsubscribe setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
}
return cell;
}
and then the btn click method as
- (IBAction)clickBtnSubscribe:(id)sender {
UIButton *button = (UIButton*)sender;
NSLog(#"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];
if (![_arraybtnState containsObject:tagnum] )
{
[_arraybtnState addObject:tagnum];
[button setImage:[UIImage imageNamed:#"following"] forState:UIControlStateNormal];
NSLog(#"Subscribe");
[self subscribeButton:button.tag];
}
else {
[self.arraybtnState removeObject:tagnum];
[button setImage:[UIImage imageNamed:#"follow"] forState:UIControlStateNormal];
NSLog(#"unsubscribe");
[self unsubscribeButton:button.tag];
}
}
Two easy solutions and quite fast to implement :
Keep track of the state in an array/dictionary
You can store your states in an array of states, i'll make an example.
(Note: i'm coding this without compiling, I might mispel some stuff, feel free to edit my post)
in your viewDidLoad
arrState = [[NSMutableArray alloc]init];
for (yourObject *object in dataArray){
//For every object that you use to load your tableview, this can be strings or anything really
[arrState addObject:#NO];
}
In your cellForRow
...
//This will either put YES or NO depending on the element in the state array.
[cell.button setSelected:[arrState objectAtIndex:indexPath.row]];
...
Boom, done.
You can also keep track of this in a database or anything persistent, and then you'd simply load whatever your field contains for a selected record. This is more relevant if we're talking about, for example, something like favourites or something that will be there until the user decides otherwise. If it's just to keep track of your button states during the lifetime of your view, then ignore this part of the answer.
If you need to keep it alive forever (even when the app closes), then you'd most probably need a database :)

set selected/unselected image one at a time uitableview cell in sectioned table

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;
}

Resources