Toggle UIButton on the iPhone - iphone

How can I make a button that says "Show Picture" and when it's clicked it changes to "Hide Picture". I'm new to objective C, I know how to make a button in interface builder but don't know how to switch the button's text and function. Can someone help me out?

Don't abuse the tag property. It is advise only to be used as a button identifier (for example when you have few buttons in your view you set their tags as 0, 1, 2... so can identify which button is a sender). You could set some global int i variable and change it's value accordingly.

abuse the .tag property of the button. Hook up the touch down action to this function:
-(IBAction)buttonClick:(UIButton*)sender
{
if ( sender.tag )
{
sender.tag = 0;
sender.text = #"Show Picture";
// do actions when "hide" is clicked
} else {
sender.tag = 1;
sender.text = #"Hide Picture";
// do actions when "show" is clicked
}
}

Instead of (ab)using the tag property, you could also simply toggle the button between selected and not selected, like so:
- (IBAction)myButtonAction:(id)sender
{
[sender setSelected:![sender isSelected]];
// or in Objective-C 2.0 if you're so inclined
sender.selected = !sender.selected;
}
In IB, you could then set the text for the normal and the selected state of the button directly in the inspector (or programmatically through the setTitle:forState: method).

The tricky thing with this one is that a UIButton doesn't have an "official" text properly - see the docs here:
http://developer.apple.com/iphone/library/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html
because it's designed to have multiple, separate sets of texts, displayed according to the button's current state; i.e., whether it's currently enabled or disabled, highlighted, etc. So there's not one, simple property you can set to make this work.
So, you want to declare your button like this, as both an action and an outlet:
from button.h:
// inside the class declaration
BOOL pictureShown ; // initializer not required, defaults to 0 (NO)
UIButton * sampleButton ;
// skip irrelevant lines here
#property (nonatomic, retain) IBOutlet UIButton * sampleButton ;
- (IBAction) doSampleButton ;
Hook both of those up in Interface Builder, and then change the text using the setTitle:forState: method (and in this case, I've specified all the states, so the title stays the same across all of them). For example:
from button.m:
#synthesize sampleButton ;
- (IBAction) doSampleButton {
if (pictureShown == YES) {
// hide the picture, and then...
[sampleButton setTitle: #"Show Picture" forState: (UIControlStateNormal | UIControlStateHighlighted | UIControlStateSelected | UIControlStateDisabled)] ;
pictureShown = NO ;
} else {
// show the picture, and then...
[sampleButton setTitle: #"Hide Picture" forState: (UIControlStateNormal | UIControlStateHighlighted | UIControlStateSelected | UIControlStateDisabled)] ;
pictureShown = YES ;
}
}
You'll also note that I've declared an instance variable, "pictureShown", in the view controller for the view with the button, to track the current "mode" of the button, and that I'm essentially using an if statement inside the button's action to determine which function is carried out according to the current mode of the button, and to toggle the button text accordingly.
(I'm using this to track the current mode of the button rather than, for example, examining the current title of the button directly, or other ways of storing state on the button, because MVC-wise, this sort of state belongs in the controller class.)
(If the function required a lot of code, I'd use messages to self, i.e.:
[self showPicture] ;
[self hidePicture] ;
to avoid having to cram it all inside doSampleButton, but that's purely stylistic, rather than technically required.

Related

How to identify which button was clicked

I have a Button, Once the user submits a form the button image should change to DONE.PNG, or else it will remain as SUBMIT.PNG.
I need to know the following;
1.) How can we write a method, to know which button the user clicked. (If he clicked the button when it has the DONE.PNG or SUBMIT.PNG image on it)
my button click event is -(void)buttonClicked : (id)sender {}
Normally you would set the tag of the UIButton.
-Interface or storyboard you do it under the info about the UIButton element.
-Programatically you do it like this : myButton.tag = 23;
Then in the buttonClicked you do this:
UIButton* senderButton = (UIButton*) sender;
if(senderButton.tag==23) {
// It's the button as submit
// Set button image
senderButton.tag = 5;
}
if(senderButton.tag==5) {
// Button is done
}
Hope you get it working :)
As you are using a single button and changing its image only, then there are two simple ways that you can follow:
Check the name of image of the button if its DONE.PNG then do what is required and change the image else vis-versa.
Have a variable either you can take integer(it will help you if you have even more number of image changes on same button) to track button state/image.
For example we will typedef buttonState and check against it for suitable case.
In .h file
//Before interface declaration..
typedef enum
{
ButtonStateDone = 1,
ButtonStateSubmit,
//any other state that it may have.
} ButtonState
//in interface declaration..
ButtonState buttonState; //its a class level variable that we will use to track button state.
In .m file
Initially set buttonState as you show it on initial view. suppose button shows DONE.PNG
so buttonState = ButtonStateDone;
Now, in button action you will change this
if(buttonState == ButtonStateDone)
{
//do something and change button state.
}
if(buttonState == ButtonStateSubmit)
{
//do something and change button state.
}
Here, I used typedef, it is useful if you need to have more than 2 states for button else you can simply use a BOOL variable.
You can add a tag to the button i.e. NSInteger buttonTag = [sender tag] and then have conditional statements to check the tag values to determine which button was clicked.

iPhone - call UISwitch that is generated in a UIView when a button is pressed

To clarify my question, my program has three lightbulb on the screen (Customized UIButton)
when any lightbulb is pressed, I programatically generate a UIView with a switch on it
when I turn on the switch, corresponding lightbulb will light up (change its background image)
However, I have trouble accessing this UISwitch since I can't declare it publicly
My code goes something like this:
#property buttonA;
#synthesize buttonA;//all three buttons have their background image set to 'off.png'
- (IBAction)lightBulbPressed:(UIButton *)sender
{
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(1,1, 64, 64)];
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,64,64)];
[mySwitch addTarget:self action:#selector(onOrOff) forControlEvents:UIControlEventValueChanged];
[myView addSubview:mySwitch]
[self.view addSubview:myView];
}
So what troubles me is how to program the selector onOrOff, so that it knows which switch is being touched and change the background image of corresponding button accordingly.
Think about your method:
- (IBAction)lightBulbPressed:(UIButton *)sender {
// your method
}
You already know who called it. This piece of information is stored in sender.
So you can save it and use later in onOrOff
By the way, if you are using UISwitch you have to check
UIControlEventValueChanged
and not UIControlEventTouchUpInside.
EDIT: To pass your sender you can store its value to a NSString *buttonTapped declared in your .h file
- (IBAction)lightBulbPressed:(UIButton *)sender {
if (sender == bttOne) {
buttonTapped = #"ButtonOneTapped";
} else if (sender == bttTwo) {
buttonTapped = #"ButtonTwoTapped";
} else if (sender == bttThree) {
buttonTapped = #"ButtonThreeTapped";
}
// your method
}
- (void)onOrOff {
if ([buttonTapped isEqualToString:#"ButtonOneTapped"]) {
// Button One
} else if ([buttonTapped isEqualToString:#"ButtonTwoTapped"]) {
// Button Two
} else if ([buttonTapped isEqualToString:#"ButtonThreeTapped"]) {
// Button Three
}
}
One way to do so, is taht you give them distinct tag numbers in IB, and in - (IBAction)lightBulbPressed:(UIButton *)sender method, get their tag. e.g. NSInteger pressedButtonTag = [sender tag];, and go from there.
Also, instead of alloc/init myView every time user presses a button, you can add that view in IB, add the switch to it, put in the hierarchy of the owner but not the view, and set an outlet to it in .h. Call it whenever you need it, and again, access the switch by tag e.g. ( UISwitch *mySwitch = (UISwitch *)[myView viewWithTag:kSwitchTag]; ) and do whatever you want to do (on or off), add it to the subview and remove it later. This is more efficient.

iPhone iOS 4 UIButton toggle highlighted state on and off

I got a UIButton with style "Info Dark" set up in interface builder in my iPhone 4 app. One of the properties of the button is "Highlighted", which displays a white highlight around the button.
I would like to toggle this white highlight on and off, indicating if the button function is active or not.
The button is linked for "Touch up inside" event in the interface builder with this callback:
infoButton.highlighted = !infoButton.highlighted;
After the first touch, the highlight disappears and does not toggle as I expect it to. What else do I need to do to make the highlight toggle and display the state of the button?
Thank you!
Update:
When loaded from the interface builder, the button stays highlighted, even as the view appears/disappears. What causes this to happen is the "shows touch on highlight" interface builder property. If I assign the code above to another button, the info button highlights on and off as expected. However, the touches of the info button itself interfere with the above code, causing the button to lose the "touch" highlight
Update 2: I added another info button, directly below the first info button, in the interface builder and made it glow permanently. To create the appearance of the toggle, I hide and unhide the glowInfoButton below the real one. This works as expected:
infoButton.highlighted = NO;
glowInfoButton.highlighted = YES;
glowInfoButton.enabled = NO;
glowInfoButton.hidden = YES;
- (IBAction)toggleInfoMode:(id)sender {
// infoButton.selected = !infoButton.selected;
glowInfoButton.hidden = !glowInfoButton.hidden;
}
The Highlighted image is what displays when the UIButton is being pressed, and is controlled within the UIButton itself.
You're looking for the Selected property. You can set a Selected Image in IB, and then put a infoButton.selected = !infoButton.isSelected; in your TouchUpInside callback.
The highlighted property doesn't work like that, buttons aren't toggles.
It's just to know if the button is being pressed, if I'm correct.
If you want to implement that functionality, I recommend you subclass UIButton or UIControl.
Now that I see what you really were after I would advise subclass UIButton and check for a call to an event then toggle highlight state accordingly. You can do this without adding the dummy button.
in a custom button class implementation file place the following code, or similar:
#import "HighlightedButton.h"
#implementation HighlightedButton
BOOL currentHighlightState;
-(void)toggleHighlight:(id)sender {
self.highlighted = currentHighlightState;
}
-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
//get the string indicating the action called
NSString *actionString = NSStringFromSelector(action);
//get the string for the action that you want to check for
NSString *touchUpInsideMethodName = [[self actionsForTarget:target forControlEvent:UIControlEventTouchUpInside] lastObject];
if ([touchUpInsideMethodName isEqualToString:actionString]){
//toggle variable
currentHighlightState = !currentHighlightState;
//allow the call to pass through
[super sendAction:action to:target forEvent:event];
//toggle the property after a delay (to make sure the event has processed)
[self performSelector:#selector(toggleHighlight:) withObject:nil afterDelay:.2];
} else {
//not an event we are interested in, allow it pass through with no additional action
[super sendAction:action to:target forEvent:event];
}
}
#end
That was a quick run at a proper solution, there is a flicker on toggle that you may not like. I am sure if you play around with some changes that can be corrected. I tried it and actually like it for your stated case.
The highlighted state of a UIButton is simply setting the button's alpha to 0.5f. So if you set the button to not change on highlight, then just toggle the alpha between 0.1 and 0.5.
For example:
- (void)buttonPressed:(id)sender {
if((((UIButton*)sender).alpha) != 1.0f){
[((UIButton*)sender) setAlpha:1.0f];
} else {
[((UIButton*)sender) setAlpha:0.5f];
}
}
Perhaps what you really want is
infoButton.enabled = NO;
This will dim the button and disable touches when set to no, allow normal operation when set to YES.
or in your case:
infoButton.enabled = !infoButton.isEnabled;
to toggle the availability of same.
If you put this in your touchupinside event, of course it will work only the first time. After that is disabled and does not receive touch events. You would put it in another method that decides whether or not the button should be enabled.
If you truly want it to change each time it is pressed then you probably should use a switch or you may look at the -imageForState, -setTitle:forState and/or -setTitleColor:forState methods. If you want to toggle the appearance each time it is touched, you could change these.

How to get the name of the button in an action?

I have a button named start and I want to know in the method that it calls what it's name is and I'm not really sure how to do it. This is the method the button calls.
-(IBAction) startMotion: (id)sender {
UIButton * buttonName = (UIButton *) sender;
NSLog(#"Button Name: %#", buttonName.currentTitle);
}
The NSLog prints
Button Name: (null)
You can set the title of the button through
[b setTitle:#"Start" forState:UIControlStateNormal];
and to get the title (currentTitle is read-only and may be nil):
[b currentTitle];
BTW, if you just want to differentiate multiple buttons, you can just set the tag property (an integer value) of the buttons.
Also, check if you have the button specified as an IBOutlet in your viewController class, and is it connected properly as an outlet in Interface Builder?
I would rather set a certain Tag and compare the tag value rather than reading the title of the button since you have possibility to localize your app where button titles will possibly be different.
I was using the wrong property in Interface Builder.I was using name property of button in Interface Builder instead of the title property from the button settings.

iphone sdk button tags?

I can't understand the logic og button tags. Can someone tell me how to use button tags?
For eg. There are two buttons on my view and I want to print something depending on their tags like:
if(button.tag==???)x{
}etc.
When you create the button, you can set it's tag.
myButton1.tag = 0;
myButton2.tag = 1;
Or if you're using interface builder, there's a field in the inspector to set the tag.
I assume you've linked the buttons to call the same action when they're pressed, or else you wouldn't be needing to distinguish by tag, so your method should look like:
- (IBAction)buttonPressed:(id)sender
{
UIButton *aButton = (UIButton *)sender; // we know the sender is a UIButton object, so cast it
if (aButton.tag == 0)
{
// button 1 pressed
}
else if (aButton.tag = 1)
{
// button 2 pressed
}
}
Yeah you can use the tag to retrieve the UIButtons, and apply the same logic with UIVIews (have a look at this method remembering that UIButton inherits from UIView).
Specifically where do you have problems? Can you post some code/pseudo-code of yours?