iOS UIButton disappears after setting background image to nil - ios

I have a UIButton that has no title or initial background image. When pressed, the button background image changes and when pressed again, it is set to nil. Now with iOS 6.x, the button completely disappears. Here is my code:
- (IBAction)resetAll: (id) sender {
[self reset];
for (UIView *view in self.view.subviews) {
if ([[[view class] description] isEqualToString:#"UIRoundedRectButton"]) {
UIButton *theButton = (UIButton *)view;
int nTag = theButton.tag;
switch (nTag) {
case 11: {
theButton.tag = 10;
[theButton setBackgroundImage:nil forState:UIControlStateNormal];
break;
}
case 21: {
theButton.tag = 20;
[theButton setBackgroundImage:nil forState:UIControlStateNormal];
[theButton setEnabled:YES];
break;
}
case 31: {
theButton.tag = 30;
[theButton setBackgroundImage:nil forState:UIControlStateNormal];
[theButton setEnabled:YES];
break;
}
case 41: {
theButton.tag = 40;
[theButton setBackgroundImage:nil forState:UIControlStateNormal];
[theButton setEnabled:YES];
break;
}
case 51: {
theButton.tag = 50;
[theButton setBackgroundImage:nil forState:UIControlStateNormal];
[theButton setEnabled:YES];
break;
}
}
}
}
return;
This code works fine:
- (IBAction)ButtonClicked: (id) sender {
UIButton *btn = (UIButton *)sender;
// Get the current tag value
int currentTag = [sender tag];
// Toggle the check buttons
if (currentTag == 10 || currentTag == 20 || currentTag == 30 || currentTag == 40 || currentTag == 50) {
[btn setBackgroundImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateNormal];
btn.tag = ++currentTag;
}
else
if (currentTag == 11 || currentTag == 21 || currentTag == 31 || currentTag == 41 || currentTag == 51) {
[btn setBackgroundImage:nil forState:UIControlStateNormal];
btn.tag = --currentTag;
}
[self calculate];
Any suggestions or help would be appreciated!

Instead of changing the background image of the button in the UIControlStateNormal, why not instead just change states of the button?
If you created the button programmatically, you just need to add the line
[btn setBackgroundImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateSelected];
Then, when pressed and you want it to be the arrow image:
[btn setSelected:YES];
and to set it back to the default appearance:
[btn setSelected:NO];
If you made the button in a XIB, you can set the state images by changing the state config to Selected and set the image there.

Here is the final code implementing DOC's answer. I set the default and selected state in interface builder:
- (IBAction)ButtonClicked: (id) sender {
UIButton *btn = (UIButton *)sender;
if ([btn isSelected ]) {
[btn setSelected:NO];
} else {
[btn setSelected:YES];
}
[self calculate];
}
- (IBAction)resetAll: (id) sender {
[self reset];
for (UIView *view in self.view.subviews) {
if ([[[view class] description] isEqualToString:#"UIRoundedRectButton"]) {
UIButton *theButton = (UIButton *)view;
[theButton setSelected:NO];
}
}

Just an additional answer in case (like me) there is already a good amount of logic around the selected state of the button (parent class gives state to the view based on this). If you need the button to start in an un-selected state with an image and change state to selected with the no image, then you can add a generated blank image to the selected state like so.
//Make a stupid blank image because setting to nil on a state doesn't work.
UIGraphicsBeginImageContextWithOptions(CGSizeMake(23, 23), NO, 0.0);
UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *buttonNonSelectedImage = [UIImage imageNamed:#"video-slomo"];
[self.myButton setBackgroundImage:buttonNonSelectedImage forState:UIControlStateNormal];
[self.mybutton setBackgroundImage:blank forState:UIControlStateSelected];
[self.myButton addTarget:self
action:#selector(onMyButtonPress)
forControlEvents:UIControlEventTouchUpInside];
self.myButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[self.playRateButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
[self.view addSubview:self.myButton];
Then, in your button action you can just change the state (and in my case add text).
- (void)onMyButtonPress
{
if (self.myButton.isSelected) {
[self.myButton setSelected:NO];
}
else {
[self.myButton setTitle:#"Selected"]
forState:UIControlStateSelected];
[self.myButton setSelected:YES];
}
}
The accepted answer works in most cases, I just needed the selected state for other tracking info. Happy programming.

Related

UIbutton does not reset to default after click on Reset button

I have a product filter list and I would like to reset all data to default (without click) after clicked on Reset button.
But now my case is after I clicked on Reset button, selected items will not reset accordingly and it will change to other items. You may refer to screenshot as below:-
Here is my part of related code, please help and thanks for your advice:-
FilterItemCell.m
- (void)setUpUI
{
_contentButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_contentButton setTitleColor: ThemeBlueColor
forState:UIControlStateNormal];
[_contentButton addTarget:self action:#selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_contentButton];
}
- (void)checkButtonTapped:(id)sender
{
if ([sender isSelected]) {
!_attributeItemClick ? : _attributeItemClick();
[sender setSelected: NO];
[_contentButton setImage:nil forState:0];
[_contentButton setTitleColor:ThemeBlueColor forState:UIControlStateNormal];
} else {
!_attributeItemClick ? : _attributeItemClick();
[sender setSelected: YES];
[_contentButton setImage:[UIImage imageNamed:#"isSelectYes"] forState:0];
[_contentButton setTitleColor:ThemeRedColor forState:UIControlStateNormal];
}
}
Filter_ViewController.m
- (void)setUpBottomButton
{
CGFloat buttonW = FiltrateViewScreenW/2;
CGFloat buttonH = 40;
CGFloat buttonY = ScreenH -10 - buttonH;
NSArray *titles = #[#"Reset",#"OK"];
for (NSInteger i = 0; i < titles.count; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:titles[i] forState:UIControlStateNormal];
button.tag = i;
CGFloat buttonX = i*buttonW;
button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
button.titleLabel.font = PFR16Font;
if (i == 0)
{
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"Button2-1"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(bottomButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
else if (i == 1)
{
[button setBackgroundImage:[UIImage imageNamed:#"Button1-1"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(bottomButtonClick:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
}
[_filtrateConView addSubview:button];
}
}
- (void)bottomButtonClick:(UIButton *)button
{
if (button.tag == 0) //Reset Button
{
//CURRENT CODE TO RELOAD COLLECTION VIEW DATA
[self.collectionView reloadData];
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FilterItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:FilterItemCellID forIndexPath:indexPath];
cell.attribute_name=[[self.filterItem[indexPath.section] valueForKey:#"attribute_name"]objectAtIndex:indexPath.row];
return cell;
}
for reset function you need to renew all the data as in starting like you might be storing the ticked ones in an array.
you need to refresh the array you are using to display in your collectionView.
Then you need to call reload on your collectionView.
In your function I can see only reload function call not any function for refreshing the data in the array you might be using to display in the collection view.
I hope this helps you. Do let me know in case you need anything else.

How to change Button image added to UITableview section header in ios

Here is my code
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"Add_plus_iCon_iphone_4s"] forState:UIControlStateNormal];
button.frame = CGRectMake(sectionView.frame.size.width-10, 10, 20, 20);
[button addTarget:self action:#selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
[sectionView addSubview:button];
}
- (void)btnAction:(UIButton *)sender
{
int i = [sender.titleLabel.text intValue];
NSNumber *numb;
if(i == 0)
{
numb = [NSNumber numberWithBool:NO];
sender.titleLabel.text = #"1";
[sender setImage:[UIImage imageNamed:#"Add_minus_iCon_iphone_4s"] forState:UIControlStateNormal];
[sender setImage:[UIImage imageNamed:#"Add_plus_iCon_iphone_4s"] forState:UIControlStateHighlighted];
}
else
{
numb = [NSNumber numberWithBool:YES];
sender.titleLabel.text = #"0";
[sender setImage:[UIImage imageNamed:#"Add_plus_iCon_iphone_4s"] forState:UIControlStateNormal];
[sender setImage:[UIImage imageNamed:#"Add_minus_iCon_iphone_4s"] forState:UIControlStateHighlighted];
}
}
First thing set images of button for both state (UIControlStateNormal, UIControlStateSelected) in ViewDidLoad and then do [cell.btnSelect setSelected:YES]; or [cell.btnSelect setSelected:NO]; as per requirement.
Otherwise change image for UIControlStateNormal when button tapped.
you are creating UIButton each time header load, which cause your button to reset,
1 way is to design cell in storyborad or xib and use reference,
Also have a DataSource to keep track of values
e.g.
if([dataSouce containsObject:yourItem]){
//selected button image
[cell.btnSelect setSelected:YES];
}
else{
//unselected button image
[cell.btnSelect setSelected:NO];
}

CheckBox issues with images

When I select the check box the second time it shows me the checked image, but the status is unchecked.
Here is my code:
- (void)viewDidLoad {
[super viewDidLoad];
[CheckBox setBackgroundImage:[UIImage imageNamed:#"uncheck_checkbox.png"] forState:UIControlStateNormal];
}
- (IBAction)CheckBox:(id)sender {
if (CheckBox.selected == NO)
{
CheckBox.selected = YES;
[CheckBox setBackgroundImage:[UIImage imageNamed:#"checked_checkbox.png"] forState:UIControlStateNormal];
}
else
{
CheckBox.selected = NO;
[CheckBox setBackgroundImage:[UIImage imageNamed:#"uncheck_checkbox.png"] forState:UIControlStateSelected];
}
}
Your code is totally right just you replace UIControlStateSelected to UIControlStateNormal.
You need add normal image and selected images in IB itself (or in viewDidLoad) and toggle state for button in button action like below
- (IBAction)checkBoxAction:(UIButton *)sender {
sender.selected = !sender.selected;
}
if (sender.tag==0)
{
sender.tag = 1;
[sender setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
}
else
{
sender.tag=0;
[sender setImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateNormal];
}
When create button for check box you can save address this element on array after click on every button first access to all object on array seved and set image unckeck and this button clicked set image checked.
Or
When create button for check box set tag different for every button and when click on button you should be set image unckeck for every button use tag number and set image check for button clicked.
Also one thing,
Here you use CheckBox.selected = YES/NO;
So also you can write your code like:
- (void)viewDidLoad {
[super viewDidLoad];
CheckBox.selected = NO;
[CheckBox setBackgroundImage:[UIImage imageNamed:#"uncheck_checkbox.png"] forState:UIControlStateNormal];
[CheckBox setBackgroundImage:[UIImage imageNamed:#"checked_checkbox.png"] forState:UIControlStateSelected];
}
- (IBAction)CheckBox:(id)sender {
if (CheckBox.selected == NO)
{
CheckBox.selected = YES;
}
else
{
CheckBox.selected = NO;
}
}
- (IBAction)changeState:(id)sender {
UIButton *btn=(UIButton *)sender;
if (btn.selected == NO)
{
btn.selected = YES;
[btn setBackgroundImage:[UIImage imageNamed:#"checked_checkbox.png"] forState:UIControlStateNormal];
}
else
{
btn.selected = NO;
[btn setBackgroundImage:[UIImage imageNamed:#"uncheck_checkbox.png"] forState:UIControlStateNormal];
}
}
You should set boolean value to false in viewDidLoad and then in button click
- (IBAction)btnCheckBoxClick:(id)sender
{
if (isChecked)
{
[btnCheckBox setImage:[UIImage imageNamed:#"btncheckbox.png"] forState:UIControlStateNormal];
isChecked = false;
}
else
{
[btnCheckBox setImage:[UIImage imageNamed:#"btncheckbox_selected.png"] forState:UIControlStateNormal];
isChecked = true;
}
}

UIButton causing a crash

I'm having a bit of a problem here. I've created a button and want it to change it's backgroundImage on being clicked. It's not working and I get a SIGABRT error.
The code is as follows:
- (IBAction)indicatedButton:(id)sender
{
if ([sender isSelected])
{
[sender setBackgroundImage:[UIImage imageNamed:#"completeTickBox.png"]];
}
else
{
[sender setBackgroundImage:[UIImage imageNamed:#"blankTickBox.png"]];
}
}
I think you want:
[sender setBackgroundImage:[UIImage ....] forState:UIControlStateNormal];
Here's the relevant Apple documentation on the method: https://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html#//apple_ref/occ/instm/UIButton/setBackgroundImage:forState:
So in your case, it would be:
- (IBAction)indicatedButton:(id)sender
{
if ([sender isSelected])
{
[sender setBackgroundImage:[UIImage imageNamed:#"completeTickBox.png"] forState:UIControlStateNormal];
}
else
{
[sender setBackgroundImage:[UIImage imageNamed:#"blankTickBox.png"] forState:UIControlStateNormal];
}
}
Assuming here that "sender" is actually a UIButton.
First verify you're getting a UIButton
-(IBAction indicatedButton:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
}
}
Convention tip: best practice for properties of an object is to use dot notation (isSelected is a BOOL property of UIButton)
-(IBAction indicatedButton:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
if (sender.isSelected)
{
}
}
}
If you're just using a regular button, but what you want is a "toggle" button (it's one image, or a different image), then you need to set the selected state property for the button, so that it -knows- it's selected after it's been touched (and vice versa if it isn't)
-(IBAction indicatedButton:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
if (sender.isSelected)
{
[sender setSelected:NO]; // if we were selected, we won't be now
UIImage *buttonImage = [UIImage imageNamed:#"completeTickBox.png"];
[sender setImage:buttonImage forState:UIControlStateNormal];
}
else if (!sender.isSelected)
{
[sender setSelected:YES]; // if we aren't selected, we will be now
UIImage *buttonImage = [UIImage imageNamed:#"blankTickBox.png"];
[sender setImage:buttonImage forState:UIControlStateNormal];
}
}
}
Instead of using introspection (the checking class types), if you know you want to work with a button, you could also change the button sender type from id to UIButton. You can do this without rewiring the button to the storyboard/nib
-(IBAction indicatedButton:(UIButton *)sender
{
if (sender.isSelected)
{
[sender setSelected:NO]; // if we were selected, we won't be now
UIImage *buttonImage = [UIImage imageNamed:#"completeTickBox.png"];
[sender setImage:buttonImage forState:UIControlStateNormal];
}
else if (!sender.isSelected)
{
[sender setSelected:YES]; // if we aren't selected, we will be now
UIImage *buttonImage = [UIImage imageNamed:#"blankTickBox.png"];
[sender setImage:buttonImage forState:UIControlStateNormal];
}
}
you have to cast sender as UIButton because sender is (id) and the object you want is UIButton so
put this line in your codeUIButton *btn=sender;
- (IBAction)indicatedButton:(id)sender
{
UIButton *btn= sender;
if ([btn isSelected])
{
[btn setBackgroundImage:[UIImage imageNamed:#"completeTickBox.png"] forState:UIControlStateNormal];
}
else
{
[btn setBackgroundImage:[UIImage imageNamed:#"blankTickBox.png"] forState:UIControlStateNormal];
}
}

How to Deselect the image by clicking other button?

Hi in my application I ask the user to provide feedback. This could be to rate our server for example. They do this by clicking one of two buttons, good or bad. When they select an option the image for the button changes which is what I need it to do. The problem I have is that if they select good then select bad the good button needs to revert back to the 'un selected' option. As they cannot bother be 'selected'
My button code.
- (IBAction)gd:(id)sender {
UIButton *btn = (UIButton *)sender;
if ([sender isSelected]) {
[btn setBackgroundImage:[UIImage imageNamed:#"rd.png"] forState:UIControlStateNormal];
[sender setSelected:NO];
}
else{
[sender setBackgroundImage:[UIImage imageNamed:#"rd1.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
}
}
- (IBAction)bd:(id)sender {
UIButton *btn1 = (UIButton *)sender;
if ([sender isSelected]) {
[btn1 setBackgroundImage:[UIImage imageNamed:#"rd.png"] forState:UIControlStateNormal];
[sender setSelected:NO];
}
else{
[sender setBackgroundImage:[UIImage imageNamed:#"rd1.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
}
}
I have used the above but its not working like i want its showing like in the below image.
Please tell me show to resolve this one.
Create an outlet for both buttons and set the images for both states.
- (void)initButtons {
[gdBtn setBackgroundImage:[UIImage imageNamed:#"rd.png"] forState:UIControlStateNormal];
[gdBtn setBackgroundImage:[UIImage imageNamed:#"rd1.png"] forState:UIControlStateSelected];
[bdBtn setBackgroundImage:[UIImage imageNamed:#"rd.png"] forState:UIControlStateNormal];
[bdBtn setBackgroundImage:[UIImage imageNamed:#"rd1.png"] forState:UIControlStateSelected];
}
The actions should then look like these:
- (IBAction)gd:(UIButton *)sender {
[sender setSelected:!sender.isSelected];
[bdBtn setSelected:NO];
}
- (IBAction)bd:(UIButton *)sender {
[sender setSelected:!sender.isSelected];
[gdBtn setSelected:NO];
}
Here is your solution
Add this Function in the starting , to deselect 2 buttons whenever you tap on button:-
-(void)deselectButtons
{
for(UIView *vw in [self.view subviews])
{
if([vw isKindOfClass:([UIButton class])])
{
UIButton *btn=(UIButton *)vw;
btn.selected=FALSE;
}
}
}
for Good Button:-
- (IBAction)bd:(id)sender {
[self deselectButtons];//add this line of code
UIButton *btn1 = (UIButton *)sender;
if ([sender isSelected]) {
[btn1 setBackgroundImage:[UIImage imageNamed:#"rd.png"] forState:UIControlStateNormal];
[sender setSelected:NO];
} else {
[sender setBackgroundImage:[UIImage imageNamed:#"rd1.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
}
}
for BAD Button:-
- (IBAction)bd:(id)sender {
[self deselectButtons];//add this line of code
UIButton *btn1 = (UIButton *)sender;
if ([sender isSelected]) {
[btn1 setBackgroundImage:[UIImage imageNamed:#"rd.png"] forState:UIControlStateNormal];
[sender setSelected:NO];
} else {
[sender setBackgroundImage:[UIImage imageNamed:#"rd1.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
}
}

Resources