I have 8 buttons, I want to do so: When click on one of the buttons will be grayed out three and four are active. But it will be happening when I hold the button, but do not push it. If move finger on the button, and press it, all the buttons will be active. I tried using "exclusiveTouch" but it becomes inactive all 7 buttons.
Code:
- (void)viewDidLoad
{
qsq.exclusiveTouch = YES;
qsq2.exclusiveTouch = YES;
qsq3.exclusiveTouch = YES;
qsq4.exclusiveTouch = YES;
qsq_plr2.exclusiveTouch = YES;
qsq2_plr2.exclusiveTouch = YES;
qsq3_plr2.exclusiveTouch = YES;
qsq4_plr2.exclusiveTouch = YES;
}
When I click "qsq" then All the buttons are inactive. But I need qsq2, qsq3, qsq4 becomes inactive, and the other buttons are active.
It seems your design is a bit more complicated than the basic UIView properties can handle. Here's an example of the solution, only using 2 buttons.
Setup:
[button1 addTarget:self action:#selector(disableButtons:) forControlEvents:UIControlEventTouchDown];
[button1 addTarget:self action:#selector(reenableButtons:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside|UIControlEventTouchCancel];
[button2 addTarget:self action:#selector(disableButtons:) forControlEvents:UIControlEventTouchDown];
[button2 addTarget:self action:#selector(reenableButtons:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside|UIControlEventTouchCancel];
And in the callbacks, you disable the buttons that need disabled:
-(void) disableButtons:(UIButton*)button {
if (button == button1) {
button2.enabled = FALSE;
} else if (button == button2) {
button1.enabled = FALSE;
}
}
-(void) reenableButtons:(UIButton*)button {
if (button == button1 || button == button2) {
button1.enabled = TRUE;
button2.enabled = TRUE;
}
}
Related
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 :)
Hi and thanks in advance for you patience and help :)
Here is what I am doing:
- I create programmatically multiple buttons that call the same function
And what I want to accomplish:
- after a button is pressed, I want the common function to run and all the buttons to be disabled so that the function won't be called again during execution of the firs call. after the first call is ended I want to reenable the buttons.
Here is how I create the buttons:
#interface ViewController ()
{
UIButton *button;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
int tagForTheButton = 0;
int yPossition = 0;
int xPossition = 0;
for (int numberOfTheColomn = 0; numberOfTheColomn < 6; numberOfTheColomn++) {
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.adjustsImageWhenHighlighted = NO;
button.frame = CGRectMake(xPossition, yPossition, 64, 64);
button.tag = tagForTheButton;
[button setTitle:title forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.scroll addSubview:button];
yPossition=yPossition+100;
tagForTheButton++;
}
}
-(void)buttonPressed:(id)sender{
//This is my attempt to disable the buttons
//previous mistake used 2578
for (int numberForIncrease; numberForIncrease<6; numberForIncrease++) {
if (button.tag == numberForIncrease) {
UIButton *btn = (UIButton*)[self.scroll viewWithTag:numberForIncrease];
btn.enabled=NO;
[btn setUserInteractionEnabled:NO];
}
}
}
You must be disabling it incorrectly. The docs for UIButton.enabled state:
If the enabled state is NO, the control ignores touch events and
subclasses may draw differently.
Check that DisableButton is being called by adding an NSLog() call, & do away with the DisableButton method altogether:
dispatch_sync(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = NO;
_btn_sync_outlet.enabled = NO;
_btn_sync_outlet.userInteractionEnabled = NO;
});
This might helps you :)
I don't understand why you need to loop from 0 to 2577 for disabling a button which you already have an iVar pointing to..?
why don't you just switch off userInteraction to your entire view (or if that is not possible to a containerView which holds all the buttons)?
[self.view setUserInteractionEnabled: NO ];
or, failing that why not just haver an iVar there?
{
BOOL _ignoreButtons;
}
-(void)buttonPressed:(id)sender{
if (!_ignoreButtons){
_ignoreButtons = YES;
//do your time consuming job, possibly on bg thread
//on completion..
_ignoreButtons = NO;
}
}
I have a button that has a selected and non-selected state.
My target action code for the button is this:
NSArray *targets = [myButton actionsForTarget:self forControlEvent:UIControlEventTouchUpInside];
if ([targets count] == 0) {
[myButton addTarget:self action:#selector(save:) forControlEvents:UIControlEventTouchUpInside];
When the button is pressed, it goes to selected state in the method.
If the button is selected, a different action should be called. Is there any unintended consequence to doing it this way or is there a way to add actions with UIControlState instead?
if (myButton.selected == NO){
[myButton addTarget:self action:#selector(save:) forControlEvents:UIControlEventTouchUpInside];
}
else{
[myButton addTarget:self action:#selector(delete:) forControlEvent:UIControlEventTouchUpInside];
}
-(IBAction)myButton:(id)sender
{
UIButton *btn = (UIButton*)sender;
btn.selected = !btn.selected;
if(btn.selected)
{
//Do whatever you want when button is selected
[self delete];
}
else
{
//Do whatever you want when button isDeselected
[self save];
}
}
Your approach might be confusing. You can use like this.
[myButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
- (void)buttonPressed:(UIButton *)sender
{
if(sender.selected)
[self save];
else
[self delete];
}
-(void)save
{
// your code
}
-(void)delete
{
// your code
}
i believe that you are wanting something like toggle button. if i am right use yourbutton.currentTitle to follow the functionality. i.e. if [youtbutton.currentTitle isEqualToString: #"save]" then you should perform save and set that to delete and vice verse
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.
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];
}