How to customize the calloutAccessoryView of a MKAnnotationView under iOS7? - ios7

Under iOS6 I did the following to set a custom image for the button of the right callout accessory view:
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setImage:[UIImage imageNamed:#"detaildisclosurebutton.png"] forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = rightButton;
That worked very well. Now I am updating the App to iOS7 and I just get a blue circle:
When I replace the image with a square image, it becomes a square. But it is blue too.
Seems to be the tintColor. I tried to set it to nil. I also tried to use buttonWithType:UIButtonTypeCustom as buttonType, but no success.
Has anyone a solution for it?

Button type UIButtonTypeDetailDisclosure tints the image by default. Use UIButtonTypeCustom instead.
If you really need UIButtonTypeDetailDisclosure (and I can't think of a reason why you would given that you're setting a custom image, you can force your image to use "always original" rendering mode:
[[UIImage imageNamed:#"detaildisclosurebutton.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]

Related

Setting UIButton image results in blue button in iOS 7

On iOS 6 SDK I wrote the following lines of code to display an image inside a button:
NSURL *thumbURL2 = [NSURL URLWithString:#"http://example.com/thumbs/2.jpg"];
NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2];
UIImage *thumb2 = [UIImage imageWithData:thumbData2];
[btn2 setImage:thumb2 forState:UIControlStateNormal];
[self.view addSubview:btn2];
But now with Xcode 5 and iOS 7 this doesn't work. The button doesn't contain the image. The button is filled with blue color.
In iOS7 there is new button type called UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), // standard system button
Check your .xib file and change button type to Custom
To do this programmatically, add this line to the viewDidLoad:
[UIButton buttonWithType:UIButtonTypeSystem];
It seems iOS 7 is using the image provided just as an Alpha mask for displaying the button's tint color.
Changing the button type to UIButtonTypeCustom did the trick for me (thanks user716216!).
Setting the image as background doesn't always work if you already have a background image, as was my case.
Swift 3, 4, 5 :
let image = UIImage(named: "my-image")
myButton.setImage(image.withRenderingMode(.alwaysOriginal), for: .normal)
There's a good chance that the image is there and you just can't see it. Try changing the button's type to UIButtonTypeCustom. If that doesn't work, set the button's background color to [UIColor clearColor];
For swift:
let aButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
The issue is the TintColor. By default, iOS throws a blue tint color over every button. You can get around it through 3 ways.
Change the tint color. [button setTintColor:[UIColor blackColor]];
This may color your image in ways you don't want it to.
As most other suggested, set the background image. [button setBackgroundImage:[UIImage...]];
Add an UIImageView to your button.
UIImageView * img = [[UIImageView alloc] initWithImage:[UIImage...]];
[button addSubView:img];
I had the same issue.
On my storyboard I had a button without any image.
I would then assign the image in the code.
IOS 7 came and I got a lot of blue images.
The resolution was simple yet confusing. If I assign any image on the storyboard and then change the image at run time it works fine.
You always must specify a starting image on the storyboard even if you are not going to use it.
This worked for me
[myButton1 setBackgroundImage:[UIImage imageNamed:#"phones.png"] forState:UIControlStateNormal];
Note:Remove front image before doing this.
Old thread, but I wanted to chime in because I just had the same problem. The issue was just that you are calling setImage when you should call setBackgroundImage.
In iOS 13 -- just set the Tint property to White, while keeping the type of the UIButton as Custom
None of the given solutions were working for me. If you do not set an initial image in Storyboard, you can still change the image of the button by using setBackgroundImage.
For your example, only a minor change is needed.
NSURL *thumbURL2 = [NSURL URLWithString:#"http://example.com/thumbs/2.jpg"];
NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2];
UIImage *thumb2 = [UIImage imageWithData:thumbData2];
[btn2 setBackgroundImage:thumb2 forState:UIControlStateNormal];
[self.view addSubview:btn2];
This Problem is called blue color problem of the button in xcode.
When we make button by code the button shows the blue tint color by default.This can be solved byt assigning tint color to black or white accordingly to your cell's color.
The code is :
UIImage *closebtnimg = [UIImage imageNamed:#"icon_uncheck.png"];
UIImage *closebtnimg1 = [UIImage imageNamed:#"icon_checked.png"];
Custombutton *button = [Custombutton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(52, 66, 25, 24)];
[button setBackgroundImage:closebtnimg forState:UIControlStateNormal];
[button setBackgroundImage:closebtnimg1 forState:UIControlStateSelected];
[button setTintColor:[UIColor whiteColor]];
[cell.contentView addSubview:button];
[button addTarget:self action:#selector(changeImage:) forControlEvents:UIControlEventTouchUpInside];
Using Xcode 9.2 none of the above solutions worked for what I was looking for.
I was looking for a solution that will let me set .normal and .selected UIControlState images inside the storyboard for their original rendering mode, but, inside the Swift file, no string literals should exist regarding the image names.
Basically, inside your code you will get the image you set inside your storyboard for .normal state and re-render it as .alwaysOriginal (Same for .selected state), then, you will set that image (which is now rendered as original and won't be affected by the tint) for the relevant state (.normal and .selected) of your UIButton.
Here it is:
// Get your .normal image (you set via your storyboard) and render it as original
let unselectedImage = yourButton.image(for: .normal)?.withRenderingMode(.alwaysOriginal)
// Set your normal image but this time rendered as original
yourButton.setImage(unselectedImage, for: .normal)
// Same for selected state
let selectedImage = yourButton.image(for: .selected)?.withRenderingMode(.alwaysOriginal)
yourButton.setImage(selectedImage, for: .selected)
This way you can set your button image states and if the image name will change, it won't affect your code.
making the tint color as clearcolor for all the four states(Default,Highlighted,selected,disabled) worked for me.
In Swift 4, initialize your UIButton and assign uyour image Data as follows:
let myButton = UIButton(type: .cutsom)
myButton.setImage(UIImage(data:myImageData), for: .normal)

How to use edge insets in iOS?

How would I use edge insets to make an image fit inside a button? I'm not sure what values to use for the arguments in UIEdgeInsetsMake(). Could I somehow use the button's width and height to set them?
I want the button to just be an image when not selected. I understand how to do the "when not selected" part, but I have no idea how to use edge insets nor what the term exactly means.
I have this at the moment:
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)];
[button setImage:image forState:!UIControlStateSelected];
Also, how would I revert to using no image once the button becomes selected?
I think I am getting what you are saying. Please let me know if I am misunderstanding your question.
Say you have myImage.png. Initialize it as the following:
[button setImage:[UIImage imageNamed:#"myImage.png"] forState:UIControlStateNormal];
Then, assuming you have connected an IBAction for the button in Interface Builder:
- (IBAction)myButtonWasPressed:(UIButton *)sender
{
[sender setImage:nil];
}

UIBarButtonItem image (or UIToolbar custom background image?..) is darker (or lighter?..) than original

I want to create custom buttons for UIToolbar (and a custom background color for UIToolbar) in XCode.
So far, I've done it like this: create UIButton, then set an image to it and then drag it to UIToolbar. It becomes UIBarButtonItem after this, but still it has an image so it's fine for me.
The problem is, that for some reason buttons' images became darker than original images (I can see it because my toolbar background is exactly the same as buttons' background), but when I press the button, I see that its image becomes original-like and then after a sec turns back to the darker one.
I've tried to do as said in this question: Image in UIButton is darker tharn original, setting highlighted image in XCode, but after this it stopped 'changing to original' at all.
So, how can I solve this? I don't really want to bring some GUI stuff like this in code if there's a way to do this by XCode... Any help would be appreciated.
EDIT:
That's the screen shot of what's going on:
And that's how they should look like with toolbar background + buttom image combined:
Now I did it in code like this:
#implementation UIBarButtonItem (CustomView)
+ (UIBarButtonItem*) barItemWithImage:(UIImage *)image target:(id)target action:(SEL)action
{
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.bounds = CGRectMake(0, 0, image.size.width, image.size.height);
[button setImage:image forState:UIControlStateNormal];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* item = [[self alloc] initWithCustomView:button];
return item;
}
#end
And the calling code:
UIBarButtonItem *item =[UIBarButtonItem barItemWithImage:[UIImage imageNamed:#"settings"] target:nil action:nil];
[self.bottomBar setItems:#[item]];
For toolbar background I use this code:
[[UIToolbar appearance] setBackgroundImage:[UIImage imageNamed:#"toolbar_background"]
forToolbarPosition:UIToolbarPositionAny
barMetrics:UIBarMetricsDefault];
The problem remains the same...
EDIT 2:
Wow, it seems like actually the UIToolbar is lighter than original...
EDIT 3:
Well. Created new project and tested the XCode storyboard-way (with UIButton), there is works fine... That's a mystery for me, totally lost here. Need some serious clarification here about possible reasons of this: my current project is huge and I'm not able to post all the code here...
Well, since nobody answered, I'll just say that I created a new project and the problem gone.
But it happened once again, and I totally don't know why. I did a really lazy and bad thing and changed image brightness for that unlucky button in some image editor =D

Change Round Rect Button background color on StateHighlighted

I'm trying to change the background color of a button when it's selected and don't want to use an image.
[mBtn setBackgroundColor:[UIColor grayColor] forState:UIControlStateHighlighted];
Any thoughts?
I'm replying to this old thread because it pops up consistently in searches for a solution to this problem and I have seen no solution elsewhere. It is truly annoying that setTintColor only applies to the highlighted state of a UIButton. Six months ago, it was equally annoying that it applied only to iOS 5, but that will hopefully be less of an issue going forward. With that in mind, I've drawn upon and combined a number of community suggestions to composite a general purpose solution to tinting a group of buttons in their normal state.
The method below accepts an NSArray of UIButtons and a set of color specifications as input. It applies the color specifications to one button using setTintColor, renders the result to a UIImage, and applies that image as the background image of the entire set of buttons. This avoids the need to create discrete image files for button colors. Also, it does so using a stretchable image so that it may work with a collection of buttons of different sizes (though note that it assumes the default corner rounding factors of UIButton). I hope you'll find it useful for iOS 5 targets.
- (void) setColorOfButtons:(NSArray*)buttons red:(float)red green:(float)green blue:(float)blue alpha:(float)alpha {
if (buttons.count == 0) {
return;
}
// get the first button
NSEnumerator* buttonEnum = [buttons objectEnumerator];
UIButton* button = (UIButton*)[buttonEnum nextObject];
// set the button's highlight color
[button setTintColor:[UIColor colorWithRed:red/255.9999f green:green/255.9999f blue:blue/255.9999f alpha:alpha]];
// clear any existing background image
[button setBackgroundImage:nil forState:UIControlStateNormal];
// place the button into highlighted state with no title
BOOL wasHighlighted = button.highlighted;
NSString* savedTitle = [button titleForState:UIControlStateNormal];
[button setTitle:nil forState:UIControlStateNormal];
[button setHighlighted:YES];
// render the highlighted state of the button into an image
UIGraphicsBeginImageContext(button.layer.frame.size);
CGContextRef graphicsContext = UIGraphicsGetCurrentContext();
[button.layer renderInContext:graphicsContext];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIImage* stretchableImage = [image stretchableImageWithLeftCapWidth:12 topCapHeight:0];
UIGraphicsEndImageContext();
// restore the button's state and title
[button setHighlighted:wasHighlighted];
[button setTitle:savedTitle forState:UIControlStateNormal];
// set background image of all buttons
do {
[button setBackgroundImage:stretchableImage forState:UIControlStateNormal];
} while (button = (UIButton*)[buttonEnum nextObject]);
}
[mBtn setTintColor:[UIColor grayColor]];
This only effects the highlighted state, so I believe that this is what you're looking for.
You can also set it from Interface Builder, from the Highlight Tint drop-down menu.
Just for people that will land here like I did when searching for changing background colors for highlighted state...
I ended up with an UIButton subclass that has a property for backgroundHighlightColor and tracks highlighting through KVO. Here's the link to GitHub: SOHighlightButton
You should be able to adapt it to any other scenario if you need more / other properties ot the UIButton to change if highlighted.
There is no method like this, setBackgroundColor: forState:
Check documentation. you need to use image.

How to set the button image for UIControlStateSelected

Hi I want to change the background of my button after I press the button i.e. the button should not change back to the previous image.
However, I am not able to do so. My code as follows. Can anyone advise how I can change the image to "custom_button_highlight" after I click on the button?
UIImage *buttonImageNormal = [UIImage imageNamed:#"custom_button"];
UIImage *stretchableButtonImageNormal = [buttonImageNormal
stretchableImageWithLeftCapWidth:12 topCapHeight:0];
UIImage *buttonImagePressed = [UIImage imageNamed:#"custom_button_highlight"];
UIImage *stretchableButtonImagePressed = [buttonImagePressed
stretchableImageWithLeftCapWidth:12 topCapHeight:0];
button.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[button setBackgroundImage:stretchableButtonImageNormal
forState:UIControlStateNormal];
[button setBackgroundImage:stretchableButtonImagePressed
forState:UIControlStateHighlighted];
[button setBackgroundImage:stretchableButtonImagePressed
forState:UIControlStateSelected];
METHOD1
I see that you are using code to generate UIButton. It's easier to use Interface builder. Try this - In Interface builder (Xcode4), create the button & open the right sidebar. After that select the button, & the type of button as custom. After that in state config, there are various states, for each state you can set an image in image. Hope this helps...
METHOD2
If you want to use code to generate UIButton (it beats me why) then you seem to be doing the right thing. Are you sure the images are there in your bundle? You did not include the image extension (like .jpg etc.)
You mentioned, that you don't want the image to change back...
then instead of setting it for the states highlighted or selected, you have to set it for the state UIControlStateNormal.
But since you need it after it's been pressed, you have to catch the event that your button has been pressed and set the background image in there.
Hope it helped ;)
[_buttonConfirm setImage:[UIImage imageNamed:#"s.png"] forState:UIControlStateSelected ];
... does what you want programatically, not the background image. But I think you should follow Srikar's answer and use interface builder if you can.