Subclass UIButton for custom images? - iphone

If I have two images for a UIButton (box with checkmark, box without checkmark), do I want to subclass UIButton? If so, how do I know when the button is pressed to set the two images for the on/off (or checked/not checked) state?
If I'm not supposed to subclass UIButton, then do I do something like this every time I want to use a checkmark button in a class?
.h
#property (nonatomic, assign) BOOL isPressed;
.m
- (IBAction)buttonPressed:(id)sender {
isPressed = !isPressed;
if (isPressed) {
UIImage *checked = [UIImage imageNamed:#"checked.png"];
[button setImage:checked forState:UIControlStateNormal];
}
else {
UIImage *unchecked = [UIImage imageNamed:#"unchecked.png"];
[button setImage:unchecked.png forState:UIControlStateNormal];
}
}

UIButton has several possible states - normal, highlighted and selected and you can assign separate images for each state. Then in action method just toggle selected state for the button and it will handle image change for you:
[button setImage:#"checked.png" forState:UIControlStateSelected];
[button setImage:#"unchecked.png" forState:UIControlStateNormal];
...
- (IBAction)buttonPressed:(id)sender {
button.selected = !button.selected;
}

Yes if what you want to do is change that particular state of the button after every press event, that's what you should do.

Related

UIButton setImage not working?

I have following code and when I call this method, it doesn't change the image of the button although there are images in the resources.
-(void)changeButton:(NSString*)button withURL:(NSString*)url {
timetableURL = url;
UIImage *btnImage;
if ([button isEqual:#"Browser"]) {
btnImage = [UIImage imageNamed:#"browser-button.png"];
[safariBtn addTarget:self action:#selector(onSafariButtonPress:) forControlEvents:UIControlEventTouchUpInside];
}
else if ([button isEqual:#"Timetable"]) {
btnImage = [UIImage imageNamed:#"browser-timetable.png"];
[safariBtn addTarget:self action:#selector(onTimetableButtonPress:) forControlEvents:UIControlEventTouchUpInside];
}
[safariBtn setImage:btnImage forState:UIControlStateNormal];
[btnImage release];
}
UPDATED
FYI: It's a button upside UIToolbar.
Some things that seem to be wrong with your code:
[btnImage release]
You've created that image using autorelease, you are not responsible for its release. This will most likely end up in weird stuff happening, i.e. what you encountered.
Are you sure that btnImage has contents after that if statement? is there a possibility that button is not equal to #"Browser" nor #"Timetable"?
Also, make sure the button is in its normal state.
Cheers
Try This ,
[safariBtn setBackgroundImage:btnImage forState:UIControlStateNormal];
No need to release btnImage ...
i think this should help you...
[safariBtn setImage:[UIImage imageNamed:#"browser-button.png"] forState:UIControlStateNormal];
may be this will help you : set the titles of button where you created it and then control if it equals the title.
[safariBtn setTitle:#"Safari" forState:UIControlStateNormal];
then control
-(void)changeButton:(NSString*)button withURL:(NSString*)url {
timetableURL = url;
UIImage *btnImage;
if ([button titleForState:UIControlStateNormal] isEqualToString:#"Safari"]) {
btnImage = [UIImage imageNamed:#"browser-button.png"];
[safariBtn addTarget:self action:#selector(onSafariButtonPress:) forControlEvents:UIControlEventTouchUpInside];
}
else if ([button titleForState:UIControlStateNormal] isEqualToString:#"Timetable"]) {
btnImage = [UIImage imageNamed:#"browser-timetable.png"];
[safariBtn addTarget:self action:#selector(onTimetableButtonPress:) forControlEvents:UIControlEventTouchUpInside];
}
[safariBtn setImage:btnImage forState:UIControlStateNormal];
[btnImage release];
}
Change
[button isEqual:#"Browser"]
To
[button isEqualToString:#"Browser"]
isEqual is testing for object equality, not string equality.
EDIT: OK, you say your button is inside a toolbar. In this case I assume you have added it as a customview to a UIBarbuttonItem? You need to go through the bar button item and set the image property on the custom view of the bar button item, I think (though I'm not sure) once you've added a button as a custom view, the bar button item makes it's own copy so you are not talking to it any more via safariBtn.
You can access the toolbar items via
for (UIBarButtonItem *barItem in self.toolbar.items)
Assuming this code is in your viewController. Your safariBtn will then be accessible via barItem.customView

How to change the image of button with the help of tag?

How i can change the image on button when i have only tag of that button. for instance I have 20 buttons and tag is set 0 to 19. now in a response of some action i have the tag 5 of that button and now i want to change the image of that button. how could it possible? Please help
I think you can use it:
for (UIButton *button in self.view.subviews) {
if (button.tag == 5) {
[button setBackgroundImage:[UIImage imageNamed:#"new-imagepng"] forState:UIControlStateNormal];
}
}
But I didn't check it.
The following code gives you the button you are after (superView refers to whatever view is holding your button):
UIButton *button5 = [superView viewWithTag:5];
Then you can amend the properties of the button as you see fit.
UIButton *button = (UIButton *)[myView viewWithTag:myTag];
[button setImage:... forState:...];
The myView variable is superview of the 20buttons. You can get UIButton object from the tag and can set image for your state.
Make the actionof all buttons the same, say #(selector)buttonPressed:. Then in your handler do this:
-(void)buttonPressed:(id)sender {
UIButton *button = (UIButton *) sender;
int tag = button.tag;
// respond as you wish using tag... for example:
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"img%02d.png", tag]];
[button setImage:image forState:UIControlStateNormal];
}
One more warning: better use integers 1 through 20 rather than 0 through 19. This way you avoid mistakes that might arise out of the fact that the default tagof every UIView is set to 0.

A question related to UIButton

I have taken customview in my code for UIButton.
UIButton *button= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[button addTarget:self action:#selector(checkedimage:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)checkedimage:(id)sender
{
NSLog(#"checkedimage");
if(checkImage == NO)
{
newImage = [UIImage imageNamed:#"a.png"];
checkImage=YES;
}
else if(checkImage==YES)
{
newImage = [UIImage imageNamed:#"b.png"];
checkImage=NO;
}
}
but when i click on UIButton it is not going to action checkedimage
why?
You have not set it up correctly and not really given us enough information to help you.
Have you anywhere in your code created an IBOutlet with the type of UIButton and name of button? If you have done that have you in IB assign that IBOutlet to the correct UIButton?
If you have done that as well you really should not declare a NEW UIButton in the code with the same name. It should already exist as a property in the current class you are working in.
If you have not done any of the above you need to ADD your newly created button to a view somewhere for it to be visible at all.
I advise you to read some basic tutorials on how to use IB.
There is nothing wrong with the code you posted.
Have you added this button to the view? Using interface builder?
I ran this test code based on what you sent, all works just fine:
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[button addTarget:self action:#selector(checkedimage:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 100, 120, 20);
[self.view addSubview:button];
}
-(IBAction)checkedimage:(id)sender {
NSLog(#"checkedimage");
}

What is the best way to make a UIButton checkbox?

I am trying to make a standard check box for my iPhone app from a UIButton with a title and image. The button image changes between an "unchecked" image and a "checked" image.
At first I tried subclassing UIButton but UIButton has no -init*** method to use in my -init method.
What is the best way to do this?
Thanks in advance.
You shouldn't need to subclass the UIButton class. By design, Objective-C favors composition over inheritance.
UIButton is a subclass of UIControl, which has a selected property. You can use this property to toggle the on/off behaviour of a checkbox, just the same way a UISwitch does.
You can attach an action to the button's touched up inside event, and perform the toggling in there, something like this:
// when you setup your button, set an image for the selected and normal states
[myCheckBoxButton setImage:checkedImage forState:UIControlStateSelected];
[myCheckBoxButton setImage:nonCheckedImage forState:UIControlStateNormal];
- (void)myCheckboxToggle:(id)sender
{
myCheckboxButton.selected = !myCheckboxButton.selected; // toggle the selected property, just a simple BOOL
}
Set the images in the button:
[button setImage:uncheckedImage forState:UIControlStateNormal]
[button setImage:checkedImage forState:UIControlStateSelected]
Now all you need to do is:
button.selected = state
and the correct images will display.
All you need to do is set 2 different images for the states UIControlStateNormal and UIControlStateSelected, then in your selector, changed the selected property of the button.
Here is a working example (replace image names with your own):
- (void)loadView {
// ...
UIButton *chkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[chkBtn setFrame:CGRectMake(0, 0, 300, 25)];
[chkBtn setImage:[UIImage imageNamed:#"UNCHECKED.png"]
forState:UIControlStateNormal];
[chkBtn setImage:[UIImage imageNamed:#"CHECKED.png"]
forState:UIControlStateSelected];
[chkBtn addTarget:self
action:#selector(chkBtnHandler:)
forControlEvents:UIControlEventTouchUpInside];
// Optional title change for checked/unchecked
[chkBtn setTitle:#"I am NOT checked!"
forState:UIControlStateNormal];
[chkBtn setTitle:#"I am checked!"
forState:UIControlStateSelected];
[self.view addSubview:chkBtn];
[chkBtn release], chkBtn = nil;
// ...
}
- (void)chkBtnHandler:(UIButton *)sender {
// If checked, uncheck and visa versa
[sender setSelected:!sender isSelected];
}
For anyone interested in the future - instead of doing it yourself just download the link below from GitHub and it has it subclassed from UIControl already and functions perfectly as a checkbox. Also includes a sample project on how easy it is to use:
https://github.com/Brayden/UICheckbox
I have used M13Checkbox in one of my projects. Works ok.
https://github.com/Marxon13/M13Checkbox
Did you try overriding the initWithCoder method, just in case it is loaded from a nib somehow?
UIImage* nonCheckedImage=[UIImage imageNamed:#"ic_check_box_outline_blank_grey600_48dp.png"];//[UIImage init
UIImage* CheckedImage=[UIImage imageNamed:#"ic_check_box_black_48dp.png"];//[UIImage init
//ic_check_box_black_48dp.png
[_checkBox setImage:CheckedImage forState:UIControlStateSelected];
[_checkBox setImage:nonCheckedImage forState:UIControlStateNormal];
}
- (IBAction)checkBoxToggle:(id)sender {
_checkBox.selected = !_checkBox.selected; // toggle the selected property, just a simple BOOL
}
the image you can use google icon
Try this:-
-(IBAction)clickCheckButton:(UIButton *)sender {
if (sender.tag==0) {
sender.tag = 1;
[sender setImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateNormal];
}else
{
sender.tag = 0;
[sender setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal]; } } sender.tag = 0;
[sender setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
}
}
Why not use a switch - UISwitch? This is used to display an element showing the boolean state of a value.

iPhone UIButton with UISwitch functionality

Is there either a way to implement UISwitch with custom graphics for the switch-states?
Or as an alternative the other way round, an UIButton with UISwitch functionality?
UIButton already supports a "switch" functionality.
Just set a different image in Interface Builder for the "Selected State Configuration", and use the selected property of UIButton to toggle its state.
set the image to show on selected state:
[button setImage:[UIImage imageNamed:#"btn_graphics"] forState:UIControlStateSelected];
and then on touch up inside selector, set:
button.selected = YES;
if you want this to cancel another button's selection, set:
otherButton.selected = NO;
To build on what PGB and nurne said above, after you set your states and attach a selector (event method) you would want to put this code in that selector.
- (IBAction)cost:(id)sender
{
//Toggle current state and save
self.buttonTest.selected = !self.buttonTest.selected;
/**
The rest of your method goes here.
*/
}
For programmatically inclined:
-(void) addToggleButton {
CGRect aframe = CGRectMake(0,0,100,100);
UIImage *selectedImage = [UIImage imageNamed:#"selected"];
UIImage *unselectedImage = [UIImage imageNamed:#"unselected"];
self.toggleUIButton = [[UIButton alloc] initWithFrame:aframe];
[self.toggleUIButton setImage:unselectedImage forState:UIControlStateNormal];
[self.toggleUIButton setImage:selectedImage forState:UIControlStateSelected];
[self.toggleUIButton addTarget:self
action:#selector(clickToggle:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.toggleUIButton];
}
-(void) clickToggle:(id) sender {
BOOL isSelected = [(UIButton *)sender isSelected];
[(UIButton *) sender setSelected:!isSelected];
}