UIBarButtonItem ignores title attributes when in UIToolBar in iOS 8 - ios

I started a new master detail project in Xcode and I added a single UIBarButtonItem to the UIToolBar. In viewDidLoad I try and set some appearance attributes on the button.
self.button.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.redColor()], forState: .Normal)
self.button.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.greenColor()], forState: .Disabled)
The problem is that the attributes for the .Disabled state are never used, even when I set self.button.enabled = false. The button always uses the red color from the .Normal state.
What's stranger is that if I put the exact same button in the navigationBar then the disabled state works fine. What gives?

Related

Insert Icon in Navigation Bar / make BarButtonItem not clickable Swift iOS

I would like to place a bluetooth icon in my Navigation Bar, to display a connected / disconnected status.
I tried to add a BarButtonItem, set the image as my bluetooth icon, and disabled and enabled this Button. This works fine so far, and is looking ok to me, but I don't want to have this button clickable, so that it doesn't change the color on clicking on the icon.
Is this possible, or is there a way to put a UIImageView into the Navigation Bar?
Thanks!
Try disabling touch events using:
myBarButtonItem.isUserInteractionEnabled = false
navigationItem.rightBarButtonItem?.isEnabled = false
Add following code will fix your issue.
let btnBluetooth = UIButton()
btnBluetooth.setImage(#imageLiteral(resourceName: "icon_bluetooth"), for: .normal)
btnBluetooth.setImage(#imageLiteral(resourceName: "icon_bluetooth"), for: .highlighted)
btnBluetooth.tintColor = .red
let barButton = UIBarButtonItem(customView: btnBluetooth)
self.navigationItem.rightBarButtonItem = barButton
This code will add custom button where you can manage image for normal and highlight mode. For bluetooth state management, change tintColor of UIButton which you have added in UIBarButtonItem as custom view.
If you click on button, this will not change color of image.
If you don't want to add UIButton you can add UIImageView by following code.
let imgBluetooth = UIImageView(image: #imageLiteral(resourceName: "icon_bluetooth"))
imgBluetooth.tintColor = .red
let barButton = UIBarButtonItem(customView: imgBluetooth)
self.navigationItem.rightBarButtonItem = barButton
Also, make sure you have selected Render As as Template Image for your bluetooth icon which is added inside Assets.xcassets to affect tintColor. Otherwise image will be display as original. See follow:

Make selected button titlelabel to be uppercase

I have button with title "Button". After some actions this button gets "selected" status. While it is selected it have different text color that is easy to specify in interface builder.
The problem is that I also want set it's title to be uppercase. Which I don't know how.
You can set Title for Selected State of UIButton from Attribute Inspector.
Please find below image :
You can also set it programatically.
Objective-C
[btn setTitle:btn.titleLabel.text.uppercaseString forState:UIControlStateSelected];
Swift
btn.setTitle(btn.titleLabel!.text.uppercaseString, forState: .Selected)
There is a built in function for that
Button.capitalizedString
So you can use it in this way in swift
Let me assume that abtn is your IBOutlet of UIButton and Button is titlelabel of UIButton.
abtn.setTitle(abtn.titleLabel!.text.uppercaseString, forState: .Selected)
as said by kirsteins
To capitalize only the first letter you can use:
nameOfString.replaceRange(nameOfString.startIndex...nameOfString.startIndex, with: String(nameOfString[nameOfString.startIndex]).capitalizedString)
If you are setting it from code use
var myString = "string"
myString = myString.uppercaseString
button.setTitle(myString, forState: .Selected)

How to keep UIButton highlighted until a second touch?

I want to keep a button in highlighted state image until a second touch to release it to the normal state.
I've try the dispatch_async method, but it simply couldn't be back to normal state after another click.
(I'm coding in Swift so performSelector:WithObject method doesn't work either.)
I will use selected state instead of highlighted. UIButton has already the property so you don't need to create any other property.
button.setImage(image, forState: UIControlState.Normal)
button.setImage(selectedImage, forState: UIControlState.Selected)
button.addTarget(self, action: "buttonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
func buttonTapped(sender:UIButton)
{
sender.selected = !sender.selected;
}
The best solution is extend the UIButton class, add the "highlited" BOOL flag. After each click just update this flag and set different image.

Back button text colour reverts to default

I am having an issue in my app with a particular back button changing font colour for no apparent reason. I have been through all of my code and I can't see any reason for it, but when launching my app and segueing to the problem view controller, the text colour seems to be set to the default blue colour.
If I tap to go to a different tab and then go back to this view controller, then the font returns to the correct colour (white) and this is despite not having any code in viewWillAppear/Disappear viewDidAppear/Disappear.
The code I am using to set the navigation bar text colour is:
override func awakeFromNib() {
var attributes = [NSForegroundColorAttributeName: UIColor.whiteColor(),NSFontAttributeName: UIFont(name: "Avenir", size: 24)!]
self.navigationController?.navigationBar.titleTextAttributes = attributes
}
And this is in the view controller that is segued from when going to the view controller with the back button. I have tried adding this code into viewWillAppear() but even this doesn't make a difference.
Does anyone know why, on launch, my app doesn't set the back button text colour and requires a tab switch for it to update?
Please Try to write same code in view will apear method.Than it should persist style to back button
I think this code will work
self.navigationController?.navigationBar.barTintColor = UIColor.someColor()
//This sets the background colour of the navigation bar
self.navigationController?.navigationBar.tintColor = UIColor.someColor()
// This sets the colour for navigation and bar button items
self.navigationController?.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "someFont", size: 20)!, NSForegroundColorAttributeName: UIColor.blackColor()]
//This sets the attributed text for the title of the navigation bar
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.blackColor(), NSFontAttributeName: UIFont(name: "someFont", size: 17)!], forState: .Normal)
//And this sets the attributed text for the bar button item(s) on the navigation bar (So that includes the back button)
Call it in the viewWillAppear
I hope this works :)

is it possible to update UIButton title/text programmatically?

I have a UIButton, that when pressed, brings up a new view where the user can change some settings. When the view is dismissed, I'd like to update the title/text of the UIButton to reflect the new state. I'm calling:
[myButton setTitle: #"myTitle" forState: UIControlStateNormal];
[myButton setTitle: #"myTitle" forState: UIControlStateApplication];
[myButton setTitle: #"myTitle" forState: UIControlStateHighlighted];
[myButton setTitle: #"myTitle" forState: UIControlStateReserved];
[myButton setTitle: #"myTitle" forState: UIControlStateSelected];
[myButton setTitle: #"myTitle" forState: UIControlStateDisabled];
But it never seems to change from the original text/title as specified in IB.
I solved the problem just setting the title parameter for UIControlStateNormal, and it automatically works on the other states. The problem seems to be when you set another UIControlState.
[myButton setTitle: #"myTitle" forState: UIControlStateNormal];
Do you have the button specified as an IBOutlet in your view controller class, and is it connected properly as an outlet in Interface Builder (ctrl drag from new referencing outlet to file owner and select your UIButton object)? That's usually the problem I have when I see these symptoms.
Edit: While it's not the case here, something like this can also happen if you set an attributed title to the button, then you try to change the title and not the attributed title.
As of Swift 4:
button.setTitle("Click", for: .normal)
I discovered another problem. It may be a bug introduced in iOS 5, but I thought I'd point it out for anyone else who encounters it.
If you don't set any default text for the button in the XIB, no text will ever appear if you set it programmatically. And if you do set text in the XIB, any text you subsequently assign to the button programmatically will be truncated to the size of the default text.
And finally, if you're showing the view with your button and then invoke another view (like an ActionSheet) and then dismiss it, the text that you assigned to the button programmatically will be erased and the button caption will return to whatever you set up in the XIB.
Even though Caffeine Coma's issue was resolved, I would like to offer another potential cause for the title not showing up on a UIButton.
If you set an image for the UIButton using
- (void)setImage:(UIImage *)image forState:(UIControlState)state
It can cover the title. I found this out the hard way and imagine some of you end up reading this page for the same reason.
Use this method instead
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state
for the button image and the title will not be affected.
I tested this with programmatically created buttons and buttons created in a .xib
for swift :
button.setTitle("Swift", forState: UIControlState.Normal)
One more possible cause is this:
If you attempt to set the button's title in the (id)initWithNibName: ... method, then you're button property will still be nil. It hasn't yet been assigned to the UIButton.
You must be sure that you're setting your buttons in a method like (void)viewWillLoad or (void)viewWillAppear, but you probably don't want to set them as late as (void)viewDidAppear.
Turns out the docs tell you the answer! The UIButton will ignore the title change if it already has an Attributed String to use (with seems to be the default you get when using Xcode interface builder).
I used the following:
[self.loginButton
setAttributedTitle:[[NSAttributedString alloc] initWithString:#"Error !!!" attributes:nil]
forState:UIControlStateDisabled];
[self.loginButton setEnabled:NO];
Sometimes it can get really complicated. The easy way is to "refresh" the button view!
//Do stuff to your button here. For example:
[mybutton setEnabled:YES];
//Refresh it to new state.
[mybutton setNeedsDisplay];
I kept having problems with this, the only solution was to add an image and label as subviews to the uibutton. Then I discovered that the main problem was that I was using a UIButton with title: Attributed. When I changed it to Plain, just setting the titleLabel.text did the trick!
#funroll is absolutely right. Here you can see what you will need Make sure function runs on main thread only. If you do not want deal with threads you can do like this for example: create NSUserDefaults and in ViewDidLoad cheking condition was pressed button in another View or not (in another View set in NSUserDefaults needed information) and depending on the conditions set needed title for your UIButton, so [yourButton setTitle: #"Title" forState: UIControlStateNormal];
Make sure you're on the main thread.
If not, it will still save the button text. It will be there when you inspect the object in the debugger. But it won't actually update the view.

Resources