I wanted to put a timer in the title label of a tableViewController. To my surprise, storyboard let me drop a button the title and I got everything working, however, I need to button to differentiate between single and double taps. Single tap starts and stops the timer, and double tap would reset it back to zero. In order to make a button recognize both type of taps, I had to create a subclass of UIButton, which means that I am now adding the button programmatically rather than through storyboard. In viewDidLoad, I tried to add the button to the titleView of the navigationItem but nothing's showing when I run it in the simulator. I set the x,y coordinates like this
self.navigationItem.titleView.bounds.size.width/2
thinking it would place the button in the middle.
I'm not sure if I've messed up the coordinates or done something else wrong, but nothing's showing. Can you suggest how it might be done?
MMTimerButton *button = [MMTimerButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Button" forState:UIControlStateNormal];
button.frame = CGRectMake(self.navigationItem.titleView.bounds.size.width/2, self.navigationItem.titleView.bounds.size.height/2, 160.00, 40.0);
[self.navigationItem.titleView addSubview:button];
Is it possible that I can change the background image of some button when I click on another button?
I basically have 10 buttons, and I want the user to know which button is currently clicked. So what happens is each button has 2 images. One for selected and one for not selected.
I want to create a function which will reset the background images of all the buttons. And in the method for each button, I will add this reset function and then change the background image of that specific button.
Can someone suggest how is that possible?
I know how to change the background image of a button when that button is clicked.
This how my buttons look:
- (IBAction)posterButton:(id)sender {}
- (IBAction)colorInvertButton:(id)sender {}
etc..
Look up the documentation for UIButton: configure each button like this:
[button setControlImage:selectedImage forState:UIControlStateSelected];
[button setControlImage:unselectedImage forState:UIControlStateNormal];
^^this can also be done in interface builder btw.
There are also the states UIControlStateNormal | UIControlStateHighlighted and UIControlStateSelected | UIControlStateHighlighted, but this is optional.
A button also has a selected state, inherited from UIControl.
If you want to have only one selected button at a time, try this (_selectedButton should be declared as an instance variable):
- (UIButton *)selectedButton {
return _selectedButton;
}
- (void)setSelectedButton:(UIButton *)b {
if(b != _selectedButton) {
_selectedButton.selected = NO;
b.selected = YES;
_selectedButton = b;
}
}
I have a UIButton placed on a UIImageView and UILabel.
When i press down the button i want an image to show in the UIImageView and the text color of the UILabel to be changed, and when i pull up my finger i want the image to disappear and the text color of the UILabel changed back to black.
- (void)highlightActivity:(id)sender {
activityImage.image = [UIImage imageNamed:[[NSMutableString alloc] initWithString:activityName]];
activityLabel.textColor = activityColor;
}
- (void)deHighlightActivity:(id)sender {
activityLabel.textColor = [UIColor blackColor];
activityImage.image = nil;
}
It works fine when i press the button and then release, but i have a problem when tapping the button, the image isn't showing at all and the text color isn't changing.
Any ideas how to make it happen when tapping too?
Thanks,
Naor.
I think the problem is you attach both
Touch Up inside and outside on deHighlightActivity.
Because, when you pressed the button, you will release (touch up) the button eventually, if you put both touch up inside and outside on deHighlightActivity, that action will be called every time. So that your tapping action calls deHighlightActivity as well.
I don't know what exactly you are trying to do here, but looks like you have some conflicts on your design.
Is there any way I can get hold of which button I have pressed?
The buttons are created programmatically using a for loop.
I have a scroll-view of images (i used buttons for the images) where the images are taken by the user from the camera. So after the user takes a picture, the "new" picture will appear in the scrollview with the "old" pictures. The pictures are shrink into smaller sizes so what I want is that when I click the button (of any image) the image will pop up in another view in the actual size.
The button of images is created using a for loop. However, I do not know how to get hold of which button the user press. For now, when i press the button (regardless of which image/button), the last picture that is taken will always show up.
Thanks for you time.
You can use the tag property of button.
When you create the button, put a tag to each image buttons.
for(int i = 0 ; i < your_no_images ; i++){
UIButton *button = [UIButton <yourbuttontype>];
-----
button.tag = i;
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[yourView addSubView:button];
}
Now in the button click action..
-(void)buttonClicked:(UIButton*)sender{
//if you has an array of UIImage's
UIImage *clickedImage = (UIImage *)[yourImageArray objectAtIndex:sender.tag];
}
IBAction methods, like those triggered upon clicking a button, include a sender argument. sender is the object that triggered the action, for example the button that was clicked. Like this:
- (IBAction)buttonWasClicked:(id)sender
{
NSLog(#"The %# button was clicked", (UIButton *)sender.currentTitle);
}
I have a typical requirement wherein I need to keep a button in highlighted state after pressing it. I need to perform a task which should work only when a button is in highlighted state. Actually I am setting a button state to highlighted programatically.
[sender setHighlighted:YES];
And once the button is in highlighted state i need to perform another action.
- (IBAction)changeState: (UIButton*)sender
{
if (sender.highlighted == YES)
{
[self performSomeAtion:sender];
}
}
But, to my horror, whenever I press any button, the above condition is becoming true and the action is being performed repeatedly. Is there any way in which i can keep a UIButton's state to be highlighted after pressing it?
EDIT - Actually I need to perform 3 different actions for 3 different states of the button. I am already making use of selected state and normal state. Now, I need to make use of the highlighted state.
[sender setSelected:YES];
or you can simulate this effect with two image for your UIButton (notselectedimage.png and selectedimage.png), then keep track button state with a BOOL variable like BOOL buttonCurrentStatus;. Then in .h file:
BOOL buttonCurrentStatus;
and in .m file
// connect this method with Touchupinside function
- (IBAction)changeState:(UIButton*)sender
{
/* if we have multiple buttons, then we can
differentiate them by tag value of button.*/
// But note that you have to set the tag value before use this method.
if([sender tag] == yourButtontag){
if (buttonCurrentStatus == NO)
{
buttonCurrentStatus = YES;
[butt setImage: [UIImage imageNamed:#"selectedImage.png"] forState:UIControlStateNormal];
//[self performSomeAction:sender];
}
else
{
buttonCurrentStatus = NO;
[butt setImage:[UIImage imageNamed:#"notSelectedImage.png"] forState:UIControlStateNormal];
//[self performSomeAction:sender];
}
}
}
- (void)mybutton:(id)sender
{
UIButton *button = (UIButton *)sender;
button.selected = ![button isSelected]; // Important line
if (button.selected)
{
NSLog(#"Selected");
NSLog(#"%i",button.tag);
}
else
{
NSLog(#"Un Selected");
NSLog(#"%i",button.tag);
}
}
The highlighted state is used to highlight the button while it is being touched. A touch down event in the button highlights it. You should use the "selected" state instead.
If what you want to do is perform an action after the button is pressed, don't attach your method to the state change event, attach your method to the TouchUpInside event.
I just find a way, so I share it, just in case...
I kept my UIButton and set one image for each state (so you could go up to a 4 states button).
I set the UserInteractionEnabled to NO -> This button won't receive any touch.
The purpose of this first button is to show a state
I create a second custom UIButton with the same frame than the first one. For this one, none image will be set for the state (it's a fully transparent button). The purpose of this button is to catch the touch event. So I added a target to this button on the TouchUpInside event. And then when the event is fired, I change the state of the first button to Disabled, Highlighted, Selected, or none of these state (= Default state).
Everything is working like a charm!
The way you describe it, you'd be better off subclassing UIView to create your own three-state button.
Actually, you should even implement your own multistate buttonView, and manage the state it's in internally via an array of PNG for the looks and an array of states to know how many times it's been pressed.
Use [sender setSelected: YES];, I think it will be useful to you.
UIButton *btn_tmp=sender;
if(!(btn_tmp.selected))
{
[btn_temp setHighlighted:YES];
}
For iOS 7 only: you should consider setting the image renderMode to UIImageRenderingModeAlwaysTemplate. You can then use the tintColor to represent various states.
see How to apply a tintColor to a UIImage?
and
see Tint a UIView with all its subviews
The solution is tricky but it's possible.
The problem is that you tried to change the highlighted status in the button action method, which I suppose makes a clean up or check process at the end of the action and switch the highlighted status. When you try to debug it you get the highlighted = 1 but it will change at the end.
Strange but your "3 statuses button" is sometimes useful, when you'd like to keep a button in "highlighted" mode like the "selected" mode to get different action depending on the 3 statuses.
The only problem that you couldn't analyze this or switch it to highlighted mode in the button action method as this will switch to highlighted mode immediately as the user push it AND switch it back at the end.
The solution is using a dispatch.
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[theButton setHighlighted:YES];
});
This will do the trick and you could use the 3 statuses.
According to apple, UIButton has a property of imageView:
Although this property is read-only, its own properties are read/write. Use these properties to configure the appearance and behavior of the button’s view
This means that you can set in the IB (in the storyboard) a picture for this button and set the highlighted picture:
Open the Attribute inspector.
Under Button section, choose an image.
In the same section, change the State Config to Highlighted. Notice the image you chose under default is now gone and now you can set a new picture for the Highlighted.
Now you have a button with 2 state config and all you have to do during runtime to change the button.highlighted = true. Also, check the UIControl under Configuring the Control’s Attributes for more states.
You can also do it programatically as follows:
Swift (and almost the same in Objective-C):
// Setting the highlighted image
self.someButton.imageView?.highlightedImage = UIImage(named: "imageNameFromImageAssest")
// someButton will now some the highlighted image and NOT the image set in the IB
self.someButton.imageView?.highlighted = true