Programmatically set UIBarButtonItem fill color? - ios

I have a set of UIBarButtonItems from png files inside a UIToolbar.
When a user clicks on an icon, I want that icon to be filled with a color to indicate a state change.
Is it possible to do this with a single set of images (maybe by programmatically changing some attributes) or do I necessarily need two sets of images (on for each state) ?

make sure your UIImage's renderingMode is UIImageRenderingModeAlwaysTemplate first
if you initWithImage then change UIBarButtonItem's tintColor.
Although UIBarButtonItem is not a view, its tintColor property behaves
the same as that of UIView.
else if you initWithCustomView in which with a UIImageView then change the imageView's tintColor might work too
else you can setItems: animated:NO to UIToolBar every time after clicks which might not be a elegant one

It is very straight forward. You just need to do the following in code :
imgView.image = [imgView.image
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imgView.tintColor = [UIColor someColor];

Related

How to disable UIButton Tint Color?

I know my case may be rare but how do you disable the UIButton tint colour in this case?
I have a customised UIButton which has attributedTitle to help display the button pattern in different colour and alpha.
In my customised button .m file I have set something like this
[self setBackgroundImage:[self imageWithColor:[UIColor grayColor]] forState:UIControlStateSelected];
which will make the background colour to gray when the button is selected
However the real result looks like this:
Some how the text colour gets turned into white which I think is because of the tint effect on UIButtons.
Is that possible for me to have the background as grey while the text still remain the colour as set in the attributed title on selected state of the button?
Thanks
yourbutton = [UIButton buttonWithType:UIButtonTypeCustom];
(or)
If u placed button in storyboard....Choose button type as custom instead of system.
You can override setImage:forState: in UIButton subclass and change rendering mode to .alwaysOriginal.
override func setImage(_ image: UIImage?, for state: UIControlState) {
let newImage = image?.withRenderingMode(.alwaysOriginal)
super.setImage(newImage, for: state)
}
Simple, just head to the image in your assets, and set its rendering mode to "Original Image", check image below:
Follow this steps to get result:
First set UITabBar background color to clear
Now put this line in viewDidLoad method of the first page:
[[UITabBar appearance] setTintColor:SETYOURCOLOR];
Hope it will help you.

AspectFill does not fill the UIImageView

I have a button that has contentMode set to UIViewContentModeScaleAspectFill. I set it like this:
self.itemImage.imageView.contentMode = UIViewContentModeScaleAspectFill;
I also set it to Mode - Aspect Fill in IB for the button, just in case. And when I set the image, I DON'T set is as a background image:
[self.itemImage setImage:image forState:UIControlStateNormal];
However, occasionally my image does not fill the button (which I want it to do), like in this case:
See grey spaces on each side. Occurs on both iOS 6 and 7.
Any ideas?
At long last, I managed to find the solution that works in Alfie's answer to this SO question.
In short, if your UIButton (or its hidden imageView) does not respond to contentMode, use this code:
self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

iOS custom shape navigation bar

I want to developer app with a custom navigation bar like in the following images:
I think that i need to subclass UINavigationBar and add button to centre of nav bar, but i don't really know how to make navigation bar look like on image. Can you please give me advice what should i do, links to any kind of documentation would be awesome!
Similar questions about navBar that doesn't helped me:
ios back button in the bar
Use custom Navigation Bar in iOS
Custom Navigation Bar in iOS 5
rogcar
EDIT:
My idea is next: make custom navigation bar height little bigger than default size, and add background image with arrow in it and with some transparency on the edges.
If you want a button (you probably do want) you can achieve it completely by subclassing UINavigationBar. You should remember that height of UINavigationBar is read-only property.
Style but not tappable:
So let's assume we subclass the navigation bar and add button there. You could do this and it will be going look great. For example:
- (void)drawRect:(CGRect)rect
{
self.backgroundColor = [UIColor lightGrayColor];
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(self.frame.size.width/2-50, 0 , 100, 100)];
[myButton setBackgroundColor:[UIColor lightGrayColor]];
[myButton setTitle:#"Normal" forState:UIControlStateNormal];
[myButton setTitle:#"Highlighted" forState:UIControlStateHighlighted];
[self addSubview:myButton];
[self sendSubviewToBack:myButton];
}
But you will facing a problem that your button is non tapeable below UINvaigationBar. (I post an image on the bottom of the answer)
So there is clearly not a path you want to follow. Don't even try that.
Style but not tappable 2:
You may override this method in your navigation bar subclass
- (CGSize) sizeThatFits:(CGSize)size {
return CGSizeMake(custom_width, custom_height);
}
And then mask it using UIBezierPath for example
The right (tappable) way:
You have to create a view stick to your UINavigationBar. What i will do here (if you want it to every screen) is:
Make a Category of UIViewController which can draw (for example - this is easiest way) UIButton.
Style this 'UIButton' whatever you want (if you want
Pin action to 'UIButton': [btn addTarget:self action:#selector(menuShow:) forControlEvents:UIControlEventTouchUpInside];
menuShow: method should be declare in your category
You can call drawing button every time you want to redraw view controller.
As you can see there there will be two separates View: UINavigationBar and UIButton. This is allow you to set content under this little button and make it tapable.
So why just don't hide navigation bar, and use different view? Because iOS7 ;) When Apple change it in iOS7 for example then you have to rebuild your pseudo NavigationBar, with only additional view, you don't need to do anything.
You do not need to subclass UINavigationBar. Create UIView add to it UIImageView as background with image in the shape you need, add button.
Subclass UINavigationController hide UINavigationBar, add custom navigation bar.
First Hide navigation bar using -
self.navigationController.navigationBarHidden = YES;
Then create UIView with required height,height of navigationBar is 44px.Then create background image view, object of required UIButton and add all objects on created UIView as a subview.It will look like navigationBar.Thank you.
You can add your custom shaped view as titleView on the navigation bar.
Just make sure that clipsToBounds is set to NO, so it doesn't get clipped.

Customizing UIBarButtonItems in various parts of applications (background image and shape)

I want to change the background image of my UIBarButtonItems. In the root view, I want them to be a certain background image (but still rounded-rect buttons) in the nav bar, but in the next view, I have a UIToolBar where I want it to have different backgrounds yet again.
I used [[UIBarButtonItem] appearance] in my app delegate to change all of them, but I now realize for some I want it one style and for others yet another.
More importantly, I want to change not only the background image, but the shape for some. For one of the UIToolBar's UIBarButtonItems I want it to be in the shape of a back button in the navigation bar. How would I achieve this look?
Can I achieve both of these with the method outlined here?
Basically: How do I make custom UIBarButtonItems all over the app, and have some with different shapes?
If you want the buttons to look different in different view controllers, you should set them within the view controller, not in the delegate. Add code in either the init method or the viewWillAppear: method to customise the buttons. If you are customising UIToolbar items then use code similar to the link you gave. If it's for the navigation bar, do something like this:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
//Customise button with background etc that you want
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.navigationItem.leftBarButtonItem = item;
//Release item if you're not using ARC
You can use the 'appearanceWhenContainedIn' method from the UIAppearance Protocol http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAppearance_Protocol/Reference/Reference.html
So for the Toolbar, you'd use:
[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil]
And for the NavBar:
[UIBarButtonItem appearanceWhenContainedIn:[UINavigationController class], nil]

Drawing a UIButton/UIBarButtonItem to use parent bar's tintColor?

I've got a bit of a dilemma. It's not a dealbreaker, but I'm interested in a decent answer if there is one.
I've been using a UIButton with a custom subview inside of a UIBarButtonItem (as the bar button item's customView). My custom subview is not a UILabel nor is it a UIImage, which is why I'm doing what I'm doing. This UIBarButtonItem is an item on my navigation bar, and the navigation bar has a tintColor set. I want the UIButton to have that rounded-rect appearance of UIBarButtonItemStyleBordered, which means it should also take on the tintColor of its parent bar.
Current solutions out there have implemented extracting png files from UIKit for UINavigationBarDefaultButton.png and family. This would look great if I weren't setting a tintColor property; instead the button remains that "iOS navy blue", when I want, say, bright orange (not the color I'm using but you get my drift). Which brings me to my dilemma: what's the best way to make a UIButton look and act like that UIBarButtonItem style, including taking on the tintColor property? I can set that property myself on the button; it's no big deal.
Would I want to draw that UIButton's background in CoreGraphics? Is there a framework/library out there that implements this already? If I'm dreaming the impossible, just tell me. I'm not that awesome with doing CoreGraphics by hand yet, but it's definitely not outside the realm of possibility.
If this can't be done, I know I can always take the cool custom UIView I'm attempting to finagle in and just save it off as an image (and thus use UIImage inside of a UIBarButtonItem), but I'd like to see if this is possible.
This is what I'm dealing with (below). The back button looks awesome, but only because I'm not messing with it. I'd like that rightBarButtonItem to use my tintColor that I have set, but in order to give it that UIBarButtonItemStyleBordered appearance with a customView set, I'm forced to make the button use png files for its background. Below is what you see, even with tintColor set on the UIBarButtonItem (since it's using a png).
I did find this question/answer on Stack Overflow, that gets me close enough that I can wing the rest. It's a well-detailed post about how to tint a UIImage with a UIColor; I've pulled it out into a function and I've posted a gist for that right here.
Combined with that, I've defined a category method on UIButton that lets me create a button with that background image, tinted, and I plop that into an empty UIBarButtonItem.
+ (id)buttonWithBarStyleAndTintColor:(UIColor *)tintColor customView:(UIView *)customView {
UIImage *defaultNormal = [UIImage imageNamed:#"UINavigationBarDefaultButton.png"];
UIImage *defaultPressed = [UIImage imageNamed:#"UINavigationBarDefaultButtonPressed.png"];
UIImage *back = [TintImageWithTintColor(defaultNormal, tintColor)
stretchableImageWithLeftCapWidth:5.0
topCapHeight:0.0];
UIImage *pressed = [TintImageWithTintColor(defaultPressed, tintColor)
stretchableImageWithLeftCapWidth:5.0
topCapHeight:0.0];
UIButton *button = [self buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 34.0f, 30.0f);
[button addSubview:customView];
customView.userInteractionEnabled = NO;
customView.frame = CGRectCenterRectInRect(customView.frame, button.frame);
[button setBackgroundImage:back forState:UIControlStateNormal];
[button setBackgroundImage:pressed forState:UIControlStateSelected];
[button setBackgroundImage:pressed forState:UIControlStateHighlighted];
return button;
}
You can try and set the UIButton type to custom and make sure its color is clear, same for your custom view, that way the only visible view will be the UIBarButtonItem tint color.
Also if you are willing to invest, there is this tool called PaintCode that does the code for CoreGraphics for you.

Resources