Dynamic Radio Button in Objective C - ios

I want to design a dynamic radio button in my app
for (int f = 0; f<arr.count; f++) {
UILabel *lbl = [[UILabel alloc]init];
lbl.frame = CGRectMake(radio_x+10,radio_y+5 , radio_w, radio_h);
lbl.text = arr[f];
lbl.textColor = [UIColor blackColor];
[self.sub_View addSubview:lbl];
self.yourButton = [[UIButton alloc] initWithFrame:CGRectMake(xPosOfTxt,radio_y , 20, 20)];
[self.yourButton setImage: [UIImage imageNamed:#"RadioButton-Selected.png"]forState:UIControlStateNormal];
[self.yourButton setImage: [UIImage imageNamed:#"RadioButton-Unselected.png"]forState: UIControlStateSelected];
[self.yourButton setTag:baseRadioTag+f];
[self.sub_View addSubview:self.yourButton];
[self.yourButton addTarget:self action:#selector(radioSelected:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)radioSelected:(UIButton*)sender {
self.yourButton.selected = false;
sender.selected = !sender.selected;
self.yourButton = sender; }
I did like this , this is working like , selecting all the options , i want to select only one option at once , if I selected option 1 -> option 2 should be unselected . If I selected option 2 -> option 1 should be deselected.Please help me to do this .

First of all to make things easier
create a array which can hold reference of all the buttons
#interface ViewController ()
{
NSMutableArray *btnArray;
}
Create an object of Array
- (void)viewDidLoad {
[super viewDidLoad];
btnArray = [NSMutableArray new];
/// Here is your code for creating buttons
}
Now add all created buttons to this array
// this is last line from your code where you create your UI
[self.yourButton addTarget:self action:#selector(radioSelected:) forControlEvents:UIControlEventTouchUpInside];
// add this line to add your button to array
[btnArray addObject:self.yourButton];
}
Now when you click button radioSelected method is called
NOTE -: Here can be two cases according to me, but i don't know which one you require so i am explaining both of them
CASE FIRST :-When you select or deselect buttons final output can be that there can be no button selected(all can be deselected)
-(void)radioSelected:(UIButton*)sender{
// here if button is selected, deselect it otherwise select it
[sender setSelected:!sender.isSelected];
for (UIButton* btn in btnArray) {
// here we mark all other button as deselected except the current button
if(btn.tag != sender.tag){
// here when you deselect all button you can add a if statement to check that we have to deselect button only if it is selected
if(btn.isSelected){
[btn setSelected:NO];
}
}
}
}
CASE SECOND:-When atleast one button will be selected
-(void)radioSelected:(UIButton*)sender{
// here if current button is already selected we will not allow to deselect it and return
if(sender.isSelected){
return;
}
// here working is as same as described above
[sender setSelected:!sender.isSelected];
for (UIButton* btn in btnArray) {
if(btn.tag != sender.tag){
[btn setSelected:NO];
}
}
}
You can test both cases and use according to your requirement.
Hope this works for you.
And let me know if you face any issues :)

Related

How to call the button action depend upon the tag in uiTableView?

I have a button in a single cell and set tag for the button.
button uparrow creation:
UIButton *btn_uparrow=[[UIButton alloc]initWithFrame:CGRectMake(500, 20, 50, 50)];
[btn_uparrow setTitle:#"up" forState:UIControlStateNormal];
btn_uparrow.backgroundColor =[UIColor blackColor];
[btn_uparrow addTarget:self action:#selector(btn_up_arrow:) forControlEvents:UIControlEventTouchUpInside];
[btn_uparrow setTag:indexPath.row];
[cell addSubview:btn_uparrow];
uparrow button action method
-(void)btn_up_arrow:(UIButton*)click
{
i++;
NSLog(#"increment %d",i);
if(i>=5)
{
NSLog(#"button increment %d",i);
i--;
}
}
When I click the button in separate cell the increment will continue on the previous data.
Please use following code.
NSInteger tagVal = (UIButton*)click.tag;
and check tagVal variable value.
For tag in tableview
[btn_uparrow setTag:((indexPath.section & 0xFFFF) << 16) |(indexPath.row & 0xFFFF);
In button action
NSUInteger section = ((sender.tag >> 16) & 0xFFFF);
NSUInteger row = (sender.tag & 0xFFFF);
(int)i;
Try this:
-(void)btn_up_arrow:(UIButton*)click{
// get value stored in tag of the button
NSInteger tagVal = click.tag;
tagVal++;
NSLog(#"increment %d",tagVal);
if(tagVal>=5)
{
NSLog(#"button increment %d",tagVal);
tagVal--;
}
// save the value when you are done working with it
click.tag = tagVal;
}
Create a subclass of UITableViewCell
In .h file
#interface CustomTableViewCell : UITableViewCell
{
UIButton *button;
int i;//globally declaring variable i
}
#end
In .m file
// initialize the button in 'init' or any initializing function that you use,
button = [[UIButton alloc]initWithFrame:CGRectMake(10, 10, 100, 30)];
[button setTitle:#"ds" forState:UIControlStateNormal];
[button addTarget:self action:#selector(onButtonAction) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"button instance created");//MAKE SURE THIS IS PRINTED
[self addSubview:button];
-(void)onButtonAction
{
i++;
NSLog(#"increment %d",i);
if(i>=5)
{
NSLog(#"button increment %d",i);
i--;
}
}

Objective C - Remove only UIButtons from superview

I am fairly new to objective-c and I have ran into an issue that I have had a hard time solving..
I am using ShinobiDataGrid and using their prepareCellForDisplay.
To get text to display I would do this:
if([cell.coordinate.column.title isEqualToString:#"Task"]){
textCell.textField.textAlignment = NSTextAlignmentLeft;
textCell.textField.text = cellDataObj.task;
}
but for a particular cell, I am trying to add a custom button:
if([cell.coordinate.column.title isEqualToString:#"selected"]){
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 10 , 32, 32);
if(cellDataObj.selected){
[button setImage:[UIImage imageNamed:#"checked-box.png"] forState:UIControlStateNormal];
}else{
[button setImage:[UIImage imageNamed:#"unchecked-box.png"] forState:UIControlStateNormal];
}
button.tag = cell.coordinate.row.rowIndex;
[button addTarget:self action:#selector(CheckBoxPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:button];
[button removeFromSuperview];
}
and I first run the app, the checkbox appears. but when I reload my ShinobiDataGrid the checkbox appears again. I tried removing the button from the superview, but that didn't work...any suggestions ? When I reload my ShinobiDataGrid a 3rd time, the checkbox does not appear for a 3rd time, just adds another when I reload the ShinobiDataGrid the 2nd time. Here is the whole method:
- (void)shinobiDataGrid:(ShinobiDataGrid *)grid prepareCellForDisplay:(SDataGridCell *)cell
{
SDataGridTextCell* textCell = (SDataGridTextCell*)cell;
CellData *cellDataObj = [cellHolderDisplay objectAtIndex:cell.coordinate.row.rowIndex];
textCell.textField.textAlignment = NSTextAlignmentCenter;
if([cell.coordinate.column.title isEqualToString:#"selected"]){
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 10 , 32, 32);
if(cellDataObj.selected){
[button setImage:[UIImage imageNamed:#"checked-box.png"] forState:UIControlStateNormal];
}else{
[button setImage:[UIImage imageNamed:#"unchecked-box.png"] forState:UIControlStateNormal];
}
button.tag = cell.coordinate.row.rowIndex;
[button addTarget:self action:#selector(CheckBoxPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:button];
[button removeFromSuperview];
}
if([cell.coordinate.column.title isEqualToString:#"Task"]){
textCell.textField.textAlignment = NSTextAlignmentLeft;
textCell.textField.text = cellDataObj.task;
}
if([cell.coordinate.column.title isEqualToString:#"BLine. Start"]){
textCell.textField.text = cellDataObj.baselineDate;
}
}
Any suggestions ?
Here is the CheckBoxPressed method:
- (void)CheckBoxPressed:(UIButton *)sender
{
CellData *cell = [cellHolder objectAtIndex:sender.tag];
if([cell selected] == YES)
{
[[cell actualDate]setString:#""];
[[cell finishedDate] setString:#""];
[cell setSelected:NO];
}
else
{
if(([[cell actualDate] isEqualToString:#""]) && ([[cell finishedDate] isEqualToString:#""]))
{
[[cell actualDate]setString:[NSString stringWithFormat:#"%# 8:00:00 AM",[self SetSpecialDateFormat:[NSDate date]]]];
[[cell finishedDate]setString:[NSString stringWithFormat:#"%# 4:00:00 PM",[self SetSpecialDateFormat:[NSDate date]]]];
}
//actual date not populated but finish date populated
else if(([[cell actualDate]isEqualToString:#""]) && !([[cell finishedDate] isEqualToString:#""]))
{
[[cell actualDate]setString:[cell finishedDate]];
}
//finish date not populated but actual date populated
else if(!([[cell actualDate] isEqualToString:#""]) && ([[cell finishedDate] isEqualToString:#""]))
{
[[cell finishedDate]setString:[cell actualDate]];
}
[cell setSelected:YES];
}
[self UpdateEdittedCells:cell];
[self SetDisplayHolder];
//refresh grid
[gridReference reload];
}
(It's not entirely clear what effect you're after here, so I'm assuming that you would like to have a column filled with checkboxes, which are either checked or un-checked according to your data model)
The problem you are encountering is that the shinobi data grid re-uses cells, in order to optimise the memory usage. Therefore adding a button to a cell will mean that the button will be there as the cell is reused (when the grid is reloaded or scrolled).
You could remove the contents of the cell at the beginning of prepareCellForDisplay:, and then you'd have an empty cell to which you can add your button:
- (void)shinobiDataGrid:(ShinobiDataGrid *)grid prepareCellForDisplay:(SDataGridCell *)cell
{
if([cell.coordinate.column.title isEqualToString:#"selected"]){
NSArray *cellSubviews = [cell.subviews copy];
for (UIView *subview in subviews) {
[subview removeFromSuperview];
}
// Now safe to add the button
}
}
However, this isn't the best approach.
You'd be much better creating a custom cell subclass for the selected column. This cell would always have a button, and would therefore make much better use of the cell reuse mechanism.
To do this, create a subclass of SDataGridCell, and register is with the grid, in the same way as you normally would. Then, when you get a callback in prepareCellForDisplay:, you know that the type will be your custom one.
You can find specific instructions on achieving this in the ShinobiDataGrid userguide:
https://www.shinobicontrols.com/docs/ShinobiControls/ShinobiGrids/2.8.0/Standard/Normal/docs/markdown_files/DataGridUserGuide.html#How to: Creating custom cells
The example you're looking for is called "Creating custom cells", and is the last of the "How-tos", right at the bottom of the page.
This example is accompanied with a complete working sample, provided in the samples folder in the dmg that you downloaded. The difference with the sample is that it is using the datasource helper. Your code isn't, but it is fairly simple to translate the populateCell method of the data source helper into the prepareCell method you are used to using.

Change Button Text Color Programmatically for n number of buttons without changing Text Color of other button

I have n number of buttons in the scrollView. If click on a button its text color is changing but if I click another button the text color of the previous button remain unchanged. I want to change the previous button text color as default color while clicking another button. The behavior will be just like a segmented control. Please help me regarding this, I've providing my code below:
-(void) loadScrollView:(CGRect)scrollViewFrame withButtonArray:(NSArray*)buttonArray withCase: (int)ButtonCase
{
scrollView=[[UIScrollView alloc]initWithFrame:scrollViewFrame];
[scrollView setScrollEnabled:YES];
[scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setContentSize:CGSizeMake(100 * 768, 40)];
for (int i = 0; i < [buttonArray count]; i++)
{
adButtonOutLet = [[UIButton alloc] initWithFrame:CGRectMake(140*i, 0, 135, 40)];
if (ButtonCase==0) {
[adButtonOutLet setBackgroundColor:UIColorFromRGB(0X272c2f)];
[adButtonOutLet setTitleColor:UIColorFromRGB(0x969696) forState:UIControlStateNormal];
}
else
{
if (i==0) {
adButtonOutLet.backgroundColor=UIColorFromRGB(0x000000) ;
[adButtonOutLet setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
}
}
adButtonOutLet.titleLabel.font=[UIFont fontWithName:#"MyriadPro" size:14.0];
[adButtonOutLet setTitle:[buttonArray objectAtIndex:i] forState:UIControlStateNormal];
adButtonOutLet.userInteractionEnabled= YES;
[adButtonOutLet setTag:i];
[adButtonOutLet addTarget:self action:#selector(adButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:adButtonOutLet];
[self.view addSubview:scrollView];
}
}
Here is my action method:
-(void)adButtonAction:(UIButton*)sender
{
for (int i = 0; i < [menuArray count]; i++)
{
int prevTag = 0;
if (sender.tag == i && Case==0)
{
[self reloadScrollViewwithButtonTag:i];
// [sender setSelected:YES];
sender.backgroundColor=UIColorFromRGB(0x000000) ;
[sender setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
prevTag=i;
}
if (Case==1) {
sender.backgroundColor=UIColorFromRGB(0x000000) ;
[sender setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
if (sender.tag==prevTag-1) {
[sender setBackgroundColor:UIColorFromRGB(0X272c2f)];
[sender setTitleColor:UIColorFromRGB(0x969696) forState:UIControlStateNormal];
}
}
}
}
Why don't you try changing all buttons style to no selected except the one that is on the sender parameter (selected button)?
-(void)adButtonAction:(UIButton*)sender{
for (int i = 0; i < [menuArray count]; i++)
{
if (sender == menuArray[i])
{
//Selected code style
}
else{
//No selected code style
}
}
}
Considering menuArray is an array with all buttons.
This way you check and modify all styles when a button is pressed.
Hope this could help you or at last give you a clue for resolve your problem.
I don' understand everything in your adButtonAction (what is menuArray?) method but I think what you need is simple, just adapt it to your method.
First create a NSMutableArray to keep reference on your button list:
for (int i = 0; i < [buttonArray count]; i++)
{
adButtonOutLet = [[UIButton alloc] initWithFrame:CGRectMake(140*i, 0, 135, 40)];
[myButtonArray addObject:adButtonOutlet];
....
Then in you action method, set the right color:
for (UIButton* b in myButtonArray){
if(b.tag == sender.tag){
[self setSelectedColor:YES forButton:b];
// Do what you want here
}
else{
[self setSelectedColor:NO forButton:b];
}
}
With:
-(void)setSelectedColor:(BOOL)selected forButton:(UIButton)button{
if(selected){
sender.backgroundColor=UIColorFromRGB(0x000000) ;
[sender setTitleColor:UIColorFromRGB(0x179d95) forState:UIControlStateNormal];
}
else{
[sender setBackgroundColor:UIColorFromRGB(0X272c2f)];
[sender setTitleColor:UIColorFromRGB(0x969696)forState:UIControlStateNormal];
}
}
Apply state vise( Normal,Selected ) title color of button.
Just persist a selected button reference as weak.
while user clicked on button set that button state as selected instead normal.
Change last selected button state Normal instead Selected.
Check out below code that will be help you
UIButton *selectedButton;
-(void)adButtonAction:(UIButton*)sender
{
UIButton *tempButton = sender;
if (selectedButton && selectedButton!=tempButton)
{
[selectedButton setSelected:NO];
}
[tempButton setSelected:YES];
selectedButton = tempButton;
}

How to remove duplicate buttons

I created five buttons using for loop, it works well. Whenever i click restart button duplicate buttons created
-(void)buttonCreate {
for( int i = 0; i < 5; i++ )
{
oneBtn1 = [UIButton buttonWithType:UIButtonTypeCustom];
oneBtn1.frame = CGRectMake(316,i*-5+474,51,50);
[oneBtn1 setTag:i];
[oneBtn1 addTarget:self action:#selector(oneButton:) forControlEvents:UIControlEventTouchUpInside];
[oneBtn1 setImage:[UIImage imageNamed:#"1c.png"] forState:UIControlStateNormal];
[self.view addSubview:oneBtn1];
}
}
Restart button function:
-(void)restart {
[self buttonCreate];
}
I tried this one but it will remove only one button out of 5.
if(oneBtn1 != NULL) {
[oneBtn1 removeFromSuperview];
oneBtn1 = nil;
}
Problem is: How to remove duplicate buttons?
Create an array(NSMutableArray *buttonHolderArray) to hold outlets for all five buttons.
[buttonHolderArray addObject:oneBtn1];
Then you can remove/update the buttons as and when you need.
And once you dont want any button, empty the array itself. On top of this, if you wish to clear the view then simply call removeFromSuperView for all the buttons
I tried this one but it will remove only one button out of 5.
if(oneBtn1 != NULL) {
[oneBtn1 removeFromSuperview];
oneBtn1 = nil;
}
You are removing only one button, if you want to remove all then use
for ( UIButton *button in buttonHolderArray){
button removeFromSuperView];
}
You can remove by checking if the button is already created.
-(void)buttonCreate {
int tag_start = 500;
for( int i = 0; i < 5; i++ )
{
UIView * prevbtn = [self.view viewWithTag:tag_start + i];
if(prevbtn) {
[prevbtn removeFromSuperview];
}
oneBtn1 = [UIButton buttonWithType:UIButtonTypeCustom];
oneBtn1.frame = CGRectMake(316,i*-5+474,51,50);
[oneBtn1 setTag:tag_start + i];
[oneBtn1 addTarget:self action:#selector(oneButton:) forControlEvents:UIControlEventTouchUpInside];
[oneBtn1 setImage:[UIImage imageNamed:#"1c.png"] forState:UIControlStateNormal];
[self.view addSubview:oneBtn1];
}
}
use this before calling again restart method
for (UIButton *btn in self.view.subviews ) {
[btn removeFromSuperview];
}
Before the restart button clicked you can remove all the buttons from you view calling the method removeChildViewsWithKindOfClass
-(void)restart {
[self.view removeChildViewsWithKindOfClass:[UIButton class]];
[self buttonCreate];
}
-(void)removeChildViewsWithKindOfClass:(Class)classToRemove{
if (classToRemove==nil) return;
for (UIView *v in [self subviews]) {
if ([v isKindOfClass:classToRemove]) {
[v removeFromSuperview];
}
}
}
If you want to remove a specific button you can use the property tag that you have to set beforehand when you create your button and it allows you removing the button with a specific tag.

Changing a UIButton to be turned off

I have a simple button with two images for each UIControlStates.
I want this button to behave as a control and as indicator so that I can press it down - "activate" and press again "deactivate", While some other functions can cause it to be turned off ("deactivate").
My question is how can I change it's state from selected to not-selected?
Changing the selected property would not do the trick :)
You can disable the button so it can't be press able.
yourButton.enabled = NO;
and When you want it back to be press able, then you can enabled it
yourButton.enabled = YES;
Simplest way would be consider button as switch and change it's state according switch on/off. For example use BOOL variable which upon button touch gets its value YES or NO while according to it button gets its image.
- (void) buttonTouched:(id)sender
{
switchOn = !switchOn;
UIImage *buttonImage = nil;
if (switchOn == YES)
{
buttonImage = [UIImage imageNamed:#"on.png"];
}
else
{
buttonImage = [UIImage imageNamed:#"off.png"];
}
[myButton setImage:buttonImage forState:UIControlStateNormal];
[myButton setImage:buttonImage forState:UIControlStateSelected];
}
if you need to programmatically set button "disabled":
- (void) setButtonDisabled
{
switchOn = YES; //calling buttonTouched: will turn it to NO
[self buttonTouched:nil];
}

Resources