UIBarButtonItem with UIImage Always Tinted iOS 7 - objective-c

I'm trying to add a UIBarButtonItem containing a UIImage to a UIToolbar. The image keeps being tinted and I can't get it to show as the original colored image - all I want to do is display an image, verbatim, in a UIBarButtonItem! I'm following the directions in the iOS 7 transition guide to set the image rendering mode to UIImageRenderingModeAlwaysOriginal.
UIImage *image = [UIImage imageNamed:#"myImage.png"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIBarButtonItem *ratingImage = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleBordered target:nil action:nil];
[toolbar setItems:[NSArray arrayWithObjects:ratingImage, nil] animated:YES];
One thing to note is that I set the tintColor for the main UIWindow of my app right when it loads...maybe this isn't important with regard to my issue, but thought I'd mention it.

I spent an evening trying to figure this out as well. You were very close to the solution.
The trick is to instantiate the UIImage with the rendering mode.
Instead of doing:
UIImage *image = [UIImage imageNamed:#"myImage.png"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
do this:
UIImage *image = [[UIImage imageNamed:#"myImage.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
and it works!
In my case, I had dragged a Navigation bar to my viewcontroller in the IB, and added the BarButtonItem. But don't provide the item an image in the IB. Make an outlet and assign it the UIImage (like we created above) by doing this:
[myCustomBarButtonItem setImage:image];
Hope this works for you.

UIImageRenderingModeAlwaysOriginal can also be set by selecting the image in your Assets.xcassets "folder" in XCode and setting the "Render as" dropdown to "Original image".

For Swift 2.1+ it would look like this:
let image : UIImage? = UIImage(named:"myImage.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
UPDATED Swift 3
let image : UIImage? = UIImage(named:"myImage.png")!.withRenderingMode(.alwaysOriginal)

The accepted answer is fine but if you placed the UIBarButtonItem in a storyboard or xib then you can just:
Go to the Assets catalog where the image lives
Select the image
Go to the attributes inspector (cmd-opt-4)
Set "Render As" to "Original Image"
Only do this if you want all instances of this image to show up without tinting.

If you want it to work for versions of iOS less than v7, you might need to to this:
UIImage *image = [UIImage imageNamed:#"myImage.png"];
#try {
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
} #catch (NSException *exception) {
}
Since imageWithRenderingMode: is an iOS 7 method, you'll get an exception if you try and use it with a lesser version.

Related

UIBarButtonItem image stays blue and not the original color of the image?

How come the icon info.png stays blue and don't comes with the original color of that image? I am using the following code below:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"info.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(info:)];
By default, image in UINavigationBar's bar button items is rendered using template mode. You can set it to original.
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:#"info.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
style:UIBarButtonItemStylePlain
target:self
action:#selector(info:)];
Swift 3:
let image : UIImage? = UIImage.init(named: "heart.png")!.withRenderingMode(.alwaysOriginal)
I know this is too late to answer this question but I see there is a very simple way to solve this issue instead of doing some changes in the code
using Xcode
Go to the Assets --Select Image --- check Render as and select Original image instead of default property .
You can it from assets as well. Go to Assets.xcassets >> Select the image that is being used as barbutton item image. Tap on attribute inspector in right side panel. Choose render as to orignial image. It will be default earlier. You will now see colored image.
Swift 4:
let image = UIImage(named: "imageName")?.withRenderingMode(.alwaysOriginal)
navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(leftBarButtonPressed))
For Swift 2.1+ it would look like this:
let image : UIImage? = UIImage(named:"myImage.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
or simply
let image : UIImage? = UIImage(named:"myImage.png")!.imageWithRenderingMode(.AlwaysOriginal)
Because the color of barButtonItems in your app is related to the tintColor property on the application's window.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.tintColor = [UIColor redColor];
return YES;
}
Ok, got it... I set the image to it's original state first.
UIImage *image = [[UIImage imageNamed:#"info.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:image
style:UIBarButtonItemStylePlain
target:self
action:#selector(info:)];
Change the bar button item tint color from the storyboard. Or color from the image in storyboard.
The color should be your expected color as hex or rgb.

Taking a snapshot of view that isn't rendered?

Say I have a view that isn't rendered, but I want to convert it to a UIImage. It seems as though I cannot use snapshotViewAfterScreenUpdates:, since it says:
If the current view is not yet rendered, perhaps because it is not yet onscreen, the snapshot view has no visible content.
How can I convert a UIView (e.g. a UILabel) into a UIImage without having to add it to the view hierarchy?
Here is the code I am using:
UILabel *label = [[UILabel alloc] init];
label.text = #"Test";
[label sizeToFit];
UIGraphicsBeginImageContextWithOptions(label.bounds.size, NO, 0.0f);
[label drawViewHierarchyInRect:label.bounds afterScreenUpdates:NO];
UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
This causes the snapshotImage to appear black, as one might expect. Is there an API similar to snapshotViewAfterScreenUpdates: which will allow me to create the UIImage without requiring the view to be rendered?
renderInContext:, as far as I know, does not require the view to be rendered on screen:
[label.layer renderInContext:UIGraphicsGetCurrentContext()];

UITabBar unselected icon tint

I am trying to change the color of my tab bar icons when the tabs are UNselected. Right now the color is default grey and I can change the color to whatever color I want for when it IS selected.
Apple's dev library said to change the image rendering to "original" instead of its default mode "template." I did that. then it says to use initWithTitle:image:selectedImage: I tried to do that as well but I think that's where I messed up. I wrote this in my viewcontroller.m file. What's wrong here?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIImage *stat = [UIImage imageNamed:#"white_stats.png"];
stat = [stat imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
(instancetype)initWithTitle:(NSString *)nil image:(UIImage *)stat selectedImage:(UIImage *)stat;
}
The problem is that you are using the same UIImage with UIImageRenderingModeAlwaysOriginal in both places.
Your code should look something like
UIImage *stat = [UIImage imageNamed:#"white_stats.png"];
UIImage *statAlwaysOriginal = [stat imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.tabBarItem = [[UITabBarItem alloc] initWithTitle:nil image:statAlwaysOriginal selectedImage:stat];
The other thing is that there are some actual syntax errors in your post (in the UITabBarItem initialization, but I suspect you just pasted it incorrectly.

Can't get a screenshot of UIView to be displayed inside UIImageView

Here's my code to get the screenshot of the view:
if (NULL != UIGraphicsBeginImageContextWithOptions){
UIGraphicsBeginImageContextWithOptions(pagedScrollView.frame.size, NO, [[UIScreen mainScreen] scale]);
}else{
UIGraphicsBeginImageContext(pagedScrollView.frame.size);
}
[pagedScrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
screenshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imageView = [[UIImageView alloc] initWithImage:screenshotImage];
imageView.frame = CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y, imageView.frame.size.width, imageView.frame.size.height);
imageView.backgroundColor = [UIColor greenColor];
[self.view addSubview:imageView];
I'm 100% sure I have the right frame and the right view - the size of UIImageView say about it - but the thing is I can't get my UIImage to be displayed on the UIImageView.
The UIImageView is added on the view and I see a green region on it - but no image inside it, what can be wrong?
I'm using iOS 6 and ARC.
Well, I just tested your code running on my view controller's view and the capture and display worked fine. This leads me to believe that pagedScrollView is probably nil, or has a zero frame.
Either way, you'll be creating an image from a blank context and then passing it to your image view resulting in there not being any visible image.
It turns out I've been taking a screenshot of a long UIScrollView and I was always taking its first page - it had a lot of pages in it and sometimes the layer had nothing in it. It also turns out that UIImage was never released and the memory can effectively store dozens of them.

Overlay an UIImage above an UIImageView, possible? example code?

Is it possible to set an image over an other image,
respectively to overlay an image above an UIImage.
I give some code:
Headerfile:
#property (nonatomic,assign)UIImageView* imageView;
Implementationfile
UIImage *overlayImage = [UIImage imageNamed:#"lamp.png"];
The "imageView.image" has got an image and above that I will have this lamp, but later on it has to be possible to move it.
I searched some methods, but all methods gave me warnings.
Could you help me how to manage it? And is Core Animation an alternative to handle that?
Just add it as a subview. UIImageView is a UIView like any other.
UIImage *overlayImage = [UIImage imageNamed:#"lamp.png"];
UIImageView *overlayImageView = [[UIImageView alloc] initWithImage:overlayImage];
[self.imageView addSubview:overlayImageView];
You should use another UIImageView. A UIImage doesn't refer to an actual view in the interface, it's used as a reference to an image to be reused in code.
UIImageView* lampImageView= [[UIImageView alloc] initWithImage:overlayImage];
This way you can move it around anywhere over the first image view.