UIButton need clicks two times for firing its action - iphone

I have two round rect buttons. I have implemented its touch up inside action. It works fine but when my click second button just after clicking the first button, my first click has no effect. This is happening with both the buttons. I am actually trying to change background image of buttons on each click to get the effect of check box (checking/unchecking). Below is the code for for one of the buttons:
-(IBAction) checkButton2: (id) sender
{
self.checkButton2 = sender;
if ( isCheck == NO)
{
[self.checkButton2 setImage: [UIImage imageNamed:#"check.png"] forState:UIControlStateNormal];
isCheck = YES;
}
else
{
[self.checkButton2 setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
isCheck = NO;;
}
}

This is solved. Actually I was using isCheck BOOL type variable for two actions(One is given above) for two buttons and both actions were setting this variable separately which shows deviation from expected behavior.

Related

Setting Selection of a UIButton with images iphone

I have a number of UIButtons in a vertical Line. All buttons have images btnImage.png btnImage_selected.png.
The Actions are set as UIEventTouchUpInside. Now i have added selected To HighLighted state of teh button.
When I press on button it shows the selected version but when i lift the finger of , it changes back to normal.
How can I make code so when the button is pressed it changes it state and stick to selected image and when another button is pressed it automatically changes back to normal state where as other button normal state is changed to selected one.
Setting the image for the Highlighted state will only set the image when it's highlighted. You'll need to set the image for all states, when the button is pressed.
Hook up all IBActions for each button to buttonPressed
#property (nonatomic, strong) NSArray *arrayOfButtons;
- (void)viewDidLoad
{
self.arrayOfButtons = [NSArray arrayWithObjects:button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, nil];
}
- (IBAction)buttonPressed:(id)sender
{
for (UIButton *button in self.arrayOfButtons)
{
if (! [button isEqual:sender])
{
[button setImage:[UIImage imageNamed:#"btnImage.png"] forState:UIControlStateNormal];
} else
{
[button setImage:[UIImage imageNamed:#"btnImage_selected.png"] forState:UIControlStateNormal];
}
}
}
If you make the buttons in a xib you can you an IBOutletCollection to hold a reference to all the buttons. Or you can add a property that holds all the buttons.
- (NSArray *)allButtons
{
return _allButtons = _allButtons ?: #[
button01,
button02,
button03,
button04,
button05,
button06,
button07,
button08,
button09,
button10,
];
}
Now you need an method that will set one button to active
- (void)setActiveButton:(UIButton *)activeButton
{
for (UIButton *button in self.allButtons) {
button.enabled = button == activeButton;
}
}

How to hide buttons which I had allocated in for loop?

I have created 3 UIbuttons on the top of the screen. Now after clicking every button I got the 5 buttons for each at below with different background images. Below is the code for my first button(located at top) by which I got 5 images in my view controller.
-(IBAction) btnforimages1click:(id)sender {
for (int a=0; a<5 ; a++) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
buttonsforbundle1 = [[UIButton alloc]initWithFrame:CGRectMake(100*a,300 ,100 ,90 )];
[buttonsforbundle1 addTarget:self action:#selector(btn4images1:) forControlEvents:UIControlEventTouchUpInside];
buttonsforbundle1.tag = a;
[buttonsforbundle1 setBackgroundImage:[UIImage imageNamed:[bundle1 objectAtIndex:a]] forState:UIControlStateNormal];
[self.view addSubview:buttonsforbundle1];
}
}
I do the same for other two buttons also. Now here I want is, when I click any of my top 3 buttons
I just want to display the related buttons (created in for loop)
I want to hide the other buttons related to other Top most buttons.
Please suggest me how to solve this.
You have at least three options:
1) Access UI element by tag:
If you can manage to issue unique tag number in your btnforimages1click, btnforimages2click, btnforimages3click for your other 5 added UIButtons, then you can access them:
UIButton *button = (UIButton *)[self.view viewWithTag:99];
[button removeFromSuperview];
2) Keep reference of the created buttons:
// in view.h
NSMutableArray *my_created_buttons;
...
// in view init
[[my_created_buttons alloc] init];
...
-(IBAction) btnforimages1click:(id)sender {
for (UIButton *b in my_created_buttons {
[b removeFromSuperview];
}
if([my_created_buttons count]) {
[my_created_buttons removeAllObjects];
}
... let buttonsforbundle1 local variable since we store current 5 button set in array
UIButton *buttonsforbundle1;
... in your for loop add this after creating and adding to view
[my_created_buttons addObject:buttonsforbundle1];
}
You can further refactor these code eg. by making mutablearray management to other method.
3) Keep it in Interface Builder
I think it is the easiest option, create 5 UIButtons in Interface Builder and have 5 IBOutlet for them. Then in your btnforimages1click you can eg:
-(IBAction) btnforimages1click:(id)sender {
self.IBbutton1 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:0]] forState:UIControlStateNormal];
self.IBbutton2 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:1]] forState:UIControlStateNormal];
self.IBbutton3 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:2]] forState:UIControlStateNormal];
self.IBbutton4 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:3]] forState:UIControlStateNormal];
self.IBbutton5 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:4]] forState:UIControlStateNormal];
}
So you don't hide them, just change the background image. Moreover you don't have to deal with different touchUpInside event, use only one method, and in that one click method, you can distinguish between the different clicked UIButton by checking their tag (plus you have to use a variable to check which of the 3 top UIButton was clicked).

Image Checkbox in Objective-C

I'm working on a form for the iphone and I would like a female/male button choice. The buttons originally have an M and an F written on them and when you choose one, an image flips over. I managed to display the images when the buttons are pressed. The problem I was having is that they were able to both be displayed at the same time but when one is enabled the other image should disappear. I've tried to correct it and now the program crashes.
implementation file:
-(IBAction) setCheckBox2: (id) sender
{
UIImage *selected = [UIImage imageNamed:#"female.tiff"];
// UIImage *notSelected = [UIImage imageNamed:#"male.tiff"];
if (sender == selected)
{
[sender setImage:selected];
}
else
{
[sender setImage:NO];
}
Then I was going to create another function for the male image being selected. Any suggestions?
Thanks!
You are testing that sender == selected hence implying that sender is of type UIImage, and then sending setImage: to sender... with itself as parameter.
This doen't make sense. I think what you were trying to do must look something like:
-(IBAction) setCheckBox2: (UIImageView *) sender
{
UIImage *selected = [UIImage imageNamed:#"female.tiff"];
UIImage *notSelected = [UIImage imageNamed:#"male.tiff"];
if (sender.image == selected)
{
[sender setImage:notSelected];
}
else
{
[sender setImage:selected];
}
}
Why not you are using default(for not selected) and selected(for selected) property for these two state. The advantage to do this is you will not have to write a bunch of code. OK set selected image and default image.
Take a global variable of UIButton for currentSelectedButton.
connect both the UIButton with single IBActionMethod named genderButtonClicked(or you want).
Now
-(IBAction)genderButtonClicked:(UIButton)sender
{
if(currentSelectedButton)
[currentSelectedButton setSelected:FALSE];
currentSelectedButton = sender;
[currentSelectedButton setSelected:TRUE];
}
I Think this will solve your problem

Different images for highlighted UIButton state

I need 2 different images for highlighted state for an UIButton.
I've these lines of code:
- (IBAction)buttonPressed:(id)sender
{
UIImage *followImageHighlighted = [UIImage imageNamed:#"follow-hilite.png"];
UIImage *unfollowImageHighlighted = [UIImage imageNamed:#"unfollow-hilite.png"];
if ([sender isSelected]) {
// set this image for the next time the button will pressed
[sender setImage:unfollowImageHighlighted forState:UIControlStateHighlighted];
} else {
// set this image for the next time the button will pressed
[sender setImage:followImageHighlighted forState:UIControlStateHighlighted];
}
}
- (void)viewDidLoad
{
// ...
UIImage *followImage = [UIImage imageNamed:#"follow.png"];
UIImage *unfollowImage = [UIImage imageNamed:#"unfollow.png"];
[self.followButton setImage:followImage forState:UIControlStateNormal];
[self.followButton setImage:unfollowImage forState:UIControlStateSelected];
}
The problem is that every time I press the button I see the highlighted image follow-hilite.png.
Can't I change the highlighted image for a button on the road?
I think this is a bad limitation because when the button is selected (thus, "Following") and an user press it, he see the default image, then when it touch up the image is that for selected state and when the network operation is completed then the button image switch correctly to the selected one.
Ideas?
EDIT
- (IBAction)followButtonTapped:(id)sender
{
BOOL isFollowed = [sender isSelected];
NSString *urlString = isFollowed ? kUnfollowURL : kFollowURL;
// operation [...]
[self.followButton setSelected:(isFollowed) ? NO : YES];
self.user.followed = !isFollowed;
}
I explain better the problem:
button in default state: black text on white background
button in selected state: white text on black background
If the target user is not followed, the button is in default state and if I try to press it I see the correct highlighted image.
BUT if the target user is followed and the button is in selected state, if I try to press it (and hold the finger) I see the button with black text on white background. This is very ugly and this is my problem.
The IBAction is an awkward (at best, or impossible) place to configure the control. There must be some condition in your app that triggers the requirement for the different highlighted image. Configure the button when you detect that condition.
Use the "pressed" callback for taking whatever action the app is supposed to take on the press.
I've solved with:
[myButton setImage:imageSelectedHover forState:(UIControlStateSelected | UIControlStateHighlighted)];
Glad it works. You solved it by updating the application condition: self.user.followed. Now, to make it really right, try this:
- (IBAction)followButtonTapped:(id)sender
{
NSString *urlString = self.user.followed? kUnfollowURL : kFollowURL;
// operation [...]
self.user.followed = !self.user.followed;
}
The state of your model is what matters here. The selected state of the button is more like a bool that was lying around where you are keeping a copy of the real following state.
I think you need to cast sender to UIButton* before you try to modify anything important and work out your variables, because sender does not include a method or property called -isSelected. Try this instead:
- (IBAction)buttonPressed:(id)sender
{
UIImage *followImageHighlighted = [UIImage imageNamed:#"follow-hilite.png"];
UIImage *unfollowImageHighlighted = [UIImage imageNamed:#"unfollow-hilite.png"];
if ([self isSelected]) {
// set this image for the next time the button will pressed
[(UIButton*)sender setImage:unfollowImageHighlighted forState:UIControlStateHighlighted];
} else {
// set this image for the next time the button will pressed
[(UIButton*)sender setImage:followImageHighlighted forState:UIControlStateHighlighted];
}
[self isSelected] = ![self isSelected];
}

UIButton state change does not happen till after touches end

Sorry if this is a basic question, I can't find a definitive answer.
I have set up 4 buttons:
// Add the normal and selected state for each button
UIImage *buttonImage = [UIImage imageNamed:[NSString stringWithFormat:#"HotspotNumber2-%i.png",(hotspotID +1)]];
[hotspotButton setImage:buttonImage forState:UIControlStateNormal];
UIImage *buttonImageSelected = [UIImage imageNamed:[NSString stringWithFormat:#"HotspotNumber2-%is.png",(hotspotID +1)]];
[hotspotButton setImage:buttonImageSelected forState:UIControlStateSelected];
[hotspotButton setImage:buttonImageSelected forState:UIControlStateHighlighted];
[hotspotButton addTarget:self action:#selector(hotspotTouch:) forControlEvents:UIControlEventTouchDown];
And I trap the touch events in the method:
// Called when a hotspot is touched
-(void)hotspotTouch:(id)sender{
// Deselect the hotspot currently selected
if (selectedHotspot) [selectedHotspot setSelected:NO];
selectedHotspot = (UIButton *)sender;
[selectedHotspot setSelected:YES];
// Get dictionary of hot spot that is pressed
NSDictionary *hotspot = [hotspots objectAtIndex:[selectedHotspot tag]];
NSString *imageFileName = [hotspot objectForKey:ksHotspotItemKey];
if ([imageFileName length] > 0) currentImageView.image = [UIImage imageNamed:imageFileName];
}
}
The problem I have is that the highlighted image for the button does not display until the user releases their finger, which is a noticeable delay. I have seen others solve similar issues by changing the background image instead of the button state or performing a selector after a delay so the run loop gets chance to end. Both methods seem like hacks to me and would be grateful if someone could explain what is happening here and what the most robust way of achieving the effect that as soon as the user touches down on the button it changes to its highlighted state.
Thanks in advance,
Dave
Have found a work around. I have created one method for TouchDown and one for TouchUpInside and TouchUpOutside. The TouchDown simply deselects the button if it is already selected and changes my view's image. The TouchUp event sets the selected property of the button. As both the highlighted and selected images are the same the net effect is that the button changes as soon as the button is touched and remains that way after the touch up events. Code is here:
// Called when a hotspot is touched down
-(void)hotspotTouchDown:(id)sender{
// Deselect the hotspot currently selected if it exists
if (selectedHotspot) [selectedHotspot setSelected:NO];
// Get dictionary of hot spot that is pressed
NSDictionary *hotspot = [hotspots objectAtIndex:[sender tag]];
// If the class of the hotspot is 'self' then replace the current image with a new one given in the hotspot data
if ([[hotspot objectForKey:ksHotspotClassKey] isEqualToString:ksHotspotClassSelf]) {
NSString *imageFileName = [hotspot objectForKey:ksHotspotItemKey];
if ([imageFileName length] > 0) currentImageView.image = [UIImage imageNamed:imageFileName];
}
}
// Called when a hotspot is touched up
-(void)hotspotTouchUp:(id)sender{
// Set the selected property of the button
selectedHotspot = (UIButton *)sender;
[selectedHotspot setSelected:YES];
}