iPhone iOS 4 UIButton toggle highlighted state on and off - iphone

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.

Related

iOS Determine button that was programmatically created

I have made a horizontal scroll view with images and buttons in it using a for loop, what i want to do now is when a button is pressed, open the image it corresponds to full screen. The issue im having is determining which button has been pushed. I am using :
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
then :
-(void)buttonPressed:(UIButton *)sender {}
What can i do to fix this? Thanks
Which button has been pushed
Create a property to store a tag. In the buttonPressed method set the property to sender.tag
Now you can know which was the button who got pressed last.
The sender is the button that the user has tapped, so when you create the buttons you could use the tag property and set it to an index of an array where you hold your images. But this could be a bit unstable if you change the order or amount of images or buttons for example so be prepared to check for that.
one way to do so is to keep references of your button (with a property, an attribute in your class) and test if it is the good one in your buttonPressed method
- (void)buttonPressed:(UIButton *)sender {
if (sender == self.myButton) {
// DO YOUR WORK HERE
}
}
you can also create a method for this and only this one button
by the way it is better to say
- (IBAction)buttonPressed:(UIButton *)sender
you then can set the target of your button in the interface builder interface
set tag for each button in the for loop but.tag=i;
-(void)buttonPressed:(UIButton *)sender {
if (sender.tag==1){
//display image 1
}
else if ....
}

Replace or extend UIBarButtonItem selector

I'm trying to make a custom UIToolbar which handles rotation and custom arrangement. When it's in portrait mode some of the barbuttonitems will not be visible, so I add a "more" button from which pops up a little view with these items. My problem is that when my current orientation is portrait and when I select a visible barbuttonitem ( which is not in popup ) I want to close the popup if it's open. I want the smae behavior for the uibarbuttons in the popupview to close the popup after tap.
So I'm trying to replace somehow the UIBarButtonItem's selector with my own, in which I call the already defined actions, like this :
-(SEL)extendOriginal:(UIBarButtonItem *) uibb
{
if (popup) popup.hidden = YES;
[uibb.target performSelector:uibb.action];
// return ?? do what ??
}
But how do I replace the original selector to call this custom method with my custom UIToolbar as its target ? Or how could I "extend" the original selector with this call ? Sorry if question is lame :)
Edit: In other words, I want 2 actions with 2 separate targets to be executed when UIBarButtonItem is tapped.
Thanks!
This -(SEL)extendOriginal:(UIBarButtonItem *) uibb doesn't make any sense.
I assume your are setting the target and the action of the bar button item somewhere. There you can set any method with one argument id or UIBarButtonItem* as the selector.
Therefore try to change your code to
- (void)myMethod:(UIBarButtonItem *) uibb
{
if (popup) popup.hidden = YES;
// do cool stuff here
}
and set the target as
[[UIBarButtonItem alloc] initWithTitle: #"Blabla" style: UIBarButtonItemStylePlain target: self action: #selector(myMethod:)];
Finally, I found a way to do it, not the prettiest, but it works.
In the custom toolbar class I created in its layout method a UITapGestureRecognizer to handle taps. I've set the cancelsTouchesInView to false and in the
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
method I'm returning true only for my toolbar's subviews.
This way the original target and action of each UIBarButtonItem remains the same and the supplementary code to handle my popup is the action of the UIGestureRecognizer.
Another problem was to distinguish between the tapped items on the toolbar (the tapped view in touch.view is some undocumented view, yay), eventually I did it with some BOOL iVars.
I hope this will help somebody with the same problem.

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.

How to dismiss keyboard when using DecimalPad

I have a UITableView with a custom cell that has a TextField. I have the DecimalPad comes up, and as we all know, there is no done key. I previously had resolved this type of issue when I had a "Decimal only" textfield on a normal UIView by handling the TouchesEnded event and then checking to see if the TextField was the first responder and if so, it would then resign, but if that technique could work now then I'm not able to figure out who's TouchesEnded I should be using (The UIView that everything is presented on, the UITableView, the Cell, the CellControler, the TextField.. I think I've tried everything).
I'm hoping there's another, cleaner way of dealing with this.
Anyone?
I think David has the best idea - here is some Monotouch code to get you started. You will need to put this in the View Controller where the decimal pad is being shown:
UIView dismiss;
public override UIView InputAccessoryView
{
get
{
if (dismiss == null)
{
dismiss = new UIView(new RectangleF(0,0,320,27));
dismiss.BackgroundColor = UIColor.FromPatternImage(new UIImage("Images/accessoryBG.png"));
UIButton dismissBtn = new UIButton(new RectangleF(255, 2, 58, 23));
dismissBtn.SetBackgroundImage(new UIImage("Images/dismissKeyboard.png"), UIControlState.Normal);
dismissBtn.TouchDown += delegate {
textField.ResignFirstResponder();
};
dismiss.AddSubview(dismissBtn);
}
return dismiss;
}
}
If you're targeting iOS 4.0 or greater you can create an inputAccessoryView containing a Done button to attach to the keyboard that will dismiss the keyboard when tapped. Here is an example from the documentation on creating a simple inputAccessoryView.
You could dismiss it when the user taps on the background; I think that's the most intuitive way.
In Interface Builder, change your View's class to UIControl. This is a subclass of UIView, so your program will work the same way, but you also get the standard touch events.
From here it's simple, create a method for the Touch Down event:
[numberField resignFirstResponder]
Of course it might be slightly different with MonoTouch -- unfortunately I don't know much about it, but wanted to help.
Hopefully you can use the concept, and modify your code accordingly.
Or you may just add some gesture to your main view.
For example:
//Just initialise the gesture you want with action that dismisses your num pad
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
UISwipeGestureRecognizer *swipeToHideNumPad = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(hideNumPad:)];
swipeToHideNumPad.delegate = self;
swipeToHideNumPad.direction = UISwipeGestureRecognizerDirectionDown;
[swipeToHideNumPad setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:swipeToHideNumPad];
}
//action
- (void)hideNumPad:(UIGestureRecognizer *)gestureRecognizer
{
[self.amountTextField resignFirstResponder];
}

Toggle UIButton on the 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.