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];
}
Related
I have table view with custom cell and it has button i want that when user click on that button then the image of button should be changes any idea how to do this becuase i want that cellImage button image to be changed in another method.
[cell.theSyncButton addTarget:self action:#selector(syncButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.theSyncButton setTag:indexPath.row];
method:
-(IBAction)syncButtonAction:(id)sender{
// I want to change the cell.SyncButton image here
}
any idea how to do this.
[btnSync setImage:[UIImage imageNamed:#"refresh.png"] forState:UIControlStateNormal];
[btnSync setImage:[UIImage imageNamed:#"refresh-active.png"] forState:UIControlStateHighlighted];
-(IBAction)syncButtonAction:(id)sender{
UIButton *btn = (UIButton *)sender;
[btn setImage:img forState:UIControlStateSelected];
}
Instead of all that code you have all you have to do is:
UIImage *img = [UIImage imageNamed:#"yourImage.png"];
[cell.theSyncButton setImage:img forState:UIControlStateSelected];
try this..
-(IBAction)syncButtonAction:(id)sender
{
UIButton * syncButton = (UIButton *) sender;
[syncButton setBackgroundImage: <NormalImage.png>
forState: UIControlStateNormal];
[syncButton setBackgroundImage: <HighlightedImage.png
forState: UIControlStateHighlighted];
}
Here is my solution:
i use UIImageVIew as button
for example , the starIcon is an UIImageView ,which i add into my custom UITableViewCell as button.
and ArticleCell is my custom UITableViewCell class.
in UITableView dataSource method cellForRowAtIndexPath:
ArticleCell* cell = [tableView dequeueReusableCellWithIdentifier:#"reused"];
if (cell==nil) {
NSLog(#"init tableViewCell");
cell = [[ArticleCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"reused"];
UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(buttonCallback:)];
gesture.numberOfTapsRequired=1;
gesture.numberOfTouchesRequired=1;
[cell.starIcon addGestureRecognizer:gesture];
cell.starIcon.userInteractionEnabled=YES;
NSLog(#"init tableViewCell end");
}
make sure you set userInteractionEnabled == true;
then , in your buttonCallback method ,you can get UIimageView by
-(void)buttonCallback:(UIGestureRecognizer*)gestureRecognizer{
UIImageView* star = (UIImageView*)[gestureRecognizer view];
}
so , you can change your imageView.
-(IBAction)syncButtonAction:(id)sender{
[button setImage:[UIImage imageNamed:#"yourimage.png"] forState:UIControlStateNormal];
}
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.
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
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.
I want to change the image on UIButton, when User presses that button. So, I wrote
btnthumbnail2 setImage:[UIImage imageNamed:#"leaderboard_ov.png"] forState:UIControlStateNormal];
and after that I changed the view.
The image is changing but not display the changed image.I think the controll goes to next view tha's why it is happening. But I want to show the change, How can I do this?? Plz help me for this..
I am using Interface Builder, in which I added a UIButton to the view.
I defined the button selected by default and selected my image for the selected state (Use drop-down list in Inspector window to choose "Selected State Configuration" before selecting the image).
Create an IBAction in the controller and connect the button to that action.
Then see the code below:
-(IBAction) toggleUIButtonImage:(id)sender{
if ([sender isSelected]) {
[sender setImage:unselectedImage forState:UIControlStateNormal];
[sender setSelected:NO];
} else {
[sender setImage:selectedImage forState:UIControlStateSelected];
[sender setSelected:YES];
}
}
This is the simplest way that I am doing it and it works every time
-(void)buttonTouched:(id)sender
{
UIButton *btn = (UIButton *)sender;
if( [[btn imageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"icon-Locked.png"]])
{
[btn setImage:[UIImage imageNamed:#"icon-Unlocked.png"] forState:UIControlStateNormal];
// other statements
}
else
{
[btn setImage:[UIImage imageNamed:#"icon-Locked.png"] forState:UIControlStateNormal];
// other statements
}
}
You can use other similar checks for other states such as SELECTED, ENABLED, HIGHLIGHTED.
The code you have there should work fine, but I'm guessing that the button image doesn't appear changed until the next run through the event loop, so you don't see it before the view gets switched out.
It's kind of a hack, but you could try delaying the view change just slightly so that the button will update.
So instead of this:
[btnthumbnail2 setImage:[UIImage imageNamed:#"leaderboard_ov.png"] forState:UIControlStateNormal];
[self showMyOtherView];
Try this:
[btnthumbnail2 setImage:[UIImage imageNamed:#"leaderboard_ov.png"] forState:UIControlStateNormal];
[self performSelector:#selector(showMyOtherView) withObject:self afterDelay:0.01];
To change the image for the selected state you have to call setImage for state UIControlStateSelected. You can set separate images for different states (Normal, Highlighted, Disabled, Selected, etc).
If you want to change the image when the button is clicked, this way, works perfectly:
-(IBAction)buttonClicked: (id)sender
{
UIButton *buttonObj = (UIButton*)sender;
[buttonObj setBackgroundImage:[UIImage imageNamed:#"myImage.png"]
forState:UIControlStateNormal];
}
The simplest way to accomplish this is to simply set the highlighted image in Interface Builder.
Building on Nicsoft's answer.
-(void)viewDidLoad {
[super viewDidLoad];
[self.button setImage:[UIImage imageNamed:#"unselectedImageName"] forState:UIControlStateNormal];
[self.button setImage:[UIImage imageNamed:#"selectedImageName"] forState:UIControlStateSelected];
}
-(IBAction)toggleButton:(UIButton *)sender {
sender.selected = !sender.selected;
// Add logic here
}
I wrote code that does exactly this last night, and I didn't have to resort to any strange delaying tactics. In this particular case, I'm doing it from inside a tableViewCell. This is more code than you asked for, but it shows the whole process I used. As you can see, I chose not to have any special image for the period of time DURING a button touch.
// Button set up, inside cellForRowAtIndexPath:
// imageFrame is just the rect that you want the button to occupy
[self setFavorite:[[UIButton alloc] initWithFrame:imageFrame]];
[[self favorite] addTarget:self action:#selector(toggleFavorite:)
forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:[self favorite]];
[self draw];
// definition of the callback specified above
- (void) toggleFavorite:(id) sender {
if (favoriteState == 0 ){
favoriteState = 1;
} else {
favoriteState = 0;
}
[self draw];
}
// the draw method, to set the images
// favOn and favOff are statically defined at the top of the class
- (void) draw {
if (favoriteState != 0) {
[[self favorite] setBackgroundImage:favOn forState:UIControlStateNormal];
[[self favorite] setBackgroundImage:favOn forState:UIControlStateHighlighted];
} else {
[[self favorite] setBackgroundImage:favOff forState:UIControlStateNormal];
[[self favorite] setBackgroundImage:favOff forState:UIControlStateHighlighted];
}
}
Hate to add to the plethora of answers, but:
Select images in IB for the button's default and selected states.
Connect an IBAction and keep it simple.
#IBAction func buttonTapped(sender: UIButton){sender.selected = !sender.selected}
Done.