How can I tint a specific UIBarButtonItem? - iphone

In iOS 6 and xcode 4, I had this:
https://dl.dropboxusercontent.com/u/60718318/photo.PNG
which was easily created with the code
[editButton setTintColor:[UIColor theGreenColor];
But on an iOS 7 phone, with the app built with the iOS 6 SDK using xcode 5, the edit button becomes un-tinted using this same exact code. (I can only post two images maximum, so just imagine that the edit button is the same color as the back button)
Many people both here on SO and all over the internet say that the only way to tint buttons now is to call
self.navigationController.navigationBar.tintColor = [UIColor theGreenColor];
which is also referenced in WWDC sessions. However, when I try something like this, I just get the following:
https://dl.dropboxusercontent.com/u/60718318/photo-2.PNG
which is not even close to correct. And according to the WWDC session I watched, this is supposed to tint BOTH buttons rather than just 1. How can I just tint 1 button, like I could in iOS 6 in xcode 4?

I don't think this is even possible anymore, I honestly think Apple just completely removed the functionality for no reason and without actually mentioning that they did. If anyone ever sees this question and wonders how I bypassed it, I just took a picture of the old button and used it as the image for the new button.

Thats certainly very unusual since you definitely can provide said functionality. The trick is to modify the tintColor of the UIBarButtonItem's UIButton rather than directly onto the item. Heres a naive implementation of a ViewController implementing this
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = createBarButtonItem()
}
func createBarButtonItem() -> UIBarButtonItem {
let button = UIButton(frame: CGRect(origin: CGPointZero, size: CGSize(width: 44, height: 44)))
button.setTitle("Press Me", forState: .Normal)
button.addTarget(self, action: "handleButtonTap:", forControlEvents: .TouchUpInside)
button.tintColor = UIColor.blueColor()
let buttonItem = UIBarButtonItem(customView: button)
return buttonItem
}
func handleButtonTap(button: UIButton) {
button.tintColor = UIColor.redColor()
}
}
Naturally you would want to manage the state of the buttons selection so you can toggle the color, but I leave that up to you

Related

Making a button change opacity on button press UIKit

OK I feel really weird for asking this question.. I started coding in Swift after SwiftUI and just never had to know this.. but..
How do I get the default behavior of a button.. where when I press it, the opacity changes (in UIKit). I thought it would be default behavior but obviously its not..
Here is what I have so far in my button configuration
private func configure() {
layer.cornerRadius = 10
setTitleColor(.white, for: .normal)
titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline)
translatesAutoresizingMaskIntoConstraints = false
layer.borderWidth = 2
layer.borderColor = UIColor.systemPink.cgColor
}
The behavior you are describing is that of a .system UIButton as opposed to a .custom UIButton. If you create your button to be of type .system you get the proposed behavior for free. If the button is created by saying UIButton(), it is not a .system button.

TintColor not changing for UIBarButtonItem for .normal stage in case of iOS 13.2

I have tried the almost max solution and it did not help, selected state color is applying but for a normal state, it's not applying. This issue I am facing specifically in iOS13.2 only.
tabBarItem.setTitleTextAttributes([NSAttributedString.Key.font: tabFont,
NSAttributedString.Key.foregroundColor: UIColor.yellow],
for: .selected)
tabBarItem.setTitleTextAttributes([NSAttributedString.Key.font: tabFont,
NSAttributedString.Key.foregroundColor: UIColor.white],
for: UIControl.State.normal)
I have disabled the dark mode in plist. It always shows as grayed out.
It's a little unclear what the question is. It's a bug, or at least a serious behavior change, in iOS 13.
To see this, just make new project from the Tabbed App template and apply your code in the first view controller's initializer:
class FirstViewController: UIViewController {
required init?(coder: NSCoder) {
super.init(coder:coder)
let tabFont = UIFont(name: "Georgia", size: 14)!
tabBarItem.setTitleTextAttributes([.font: tabFont,
.foregroundColor: UIColor.yellow],
for: .selected)
tabBarItem.setTitleTextAttributes([.font: tabFont,
.foregroundColor: UIColor.white],
for: UIControl.State.normal)
}
}
On iOS 12, the tab bar item text is yellow when selected and white when not selected. But in iOS 13, the bar item text is gray when not selected.
I have not found a satisfactory way to solve this. As suggested in a comment, you can say something like this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tabBarController?.tabBar.unselectedItemTintColor = .white
}
But that's too broad a brush, because it tints all tab bar items and it tints the image too.
You can try using the new UITabBarItemAppearance class, but that has other undesirable side effects.
So apart from filing a bug report, there's not much you can do.

Swift UIButton not appearing on screen

I have a view in my tabbar controller where I would like to show a button. I create this button programmatically based of a condition, therefore I use the following code but nothing is appearing:
override func viewDidLoad() {
super.viewDidLoad()
if !Settings.getIsConnected() {
notConnected()
}
}
func notConnected() {
let connectBtn = UIButton(frame: CGRect(x: self.view.center.x, y: self.view.center.y, width: 200, height: 45))
connectBtn.setTitle("Connect", forState: .Normal)
connectBtn.addTarget(self, action:#selector(self.pressedConnect(_:)), forControlEvents: .TouchUpInside)
self.view.addSubview(connectBtn)
print("Button created")
}
func pressedConnect(sender: UIButton!) {
}
I am clueless on what I am doing wrong. Anyone got suggestions? Cause it does print out "Button created" so it definitely runs the code inside the noConnected() method.
Add a background color to your UIButton and add a tint color to the title. This will resolve the problem
Try moving the code to viewDidAppear and see if the button is showing up.
The frame is not correctly set when in viewDidLoad. Use the method viewDidLayoutSubviews for the earliest possible time where the frame is correctly setup for a ViewController.
With this code change, you will need some additional logic for when your button should be added as a subview though.
A programmatically created button may not show up because of more reasons, e.g:
the tint color is not set
the background color is not set
the button is not added to the view hierarchy
the button is hidden
In your case, you should change the tint color or the background color of your button.
E.g.:
Swift 4.2:
private lazy var connectButton: UIButton = {
let button = UIButton(type: .custom)
button.backgroundColor = .green
button.setTitleColor(.black, for: .normal)
button.setTitle(NSLocalizedString("Connect", comment: ""), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(connectButton)
}
You can re-check the button properties in the storyboard that it is not hidden.

Change UIBarButtonItem from UISearchBar

I'd like to change the text font and color of the Cancel button inside the UISearchBar in iOS 8. I've tried the solutions for iOS 6 and 7 already and they don't seem to work.
This was not the solution I was looking for, but it worked.
let cancelButtonAttributes: NSDictionary = [NSFontAttributeName: FONT_REGULAR_16!, NSForegroundColorAttributeName: COLOR_BLUE]
UIBarButtonItem.appearance().setTitleTextAttributes(cancelButtonAttributes, forState: UIControlState.Normal)
What you are looking for is:
//The tintColor below will change the colour of the cancel button
searchBar.tintColor = UIColor.blueColor()
But these are also useful While we are on the subject:
searchBar.placeholder = "Placeholder"
//The barTintColor changes the colour of the flashing text indicator
searchBar.barTintColor = UIColor.redColor()
//This sets the cancel button to show up
searchBar.setShowsCancelButton(true, animated: true)
//This makes the searchBar become active
searchBar.becomeFirstResponder()

Hide UIButton title

I have several UIButtons in a scrollview which I use in order to pass certain information. The information is saved in the title of each uibutton and when the button is clicked, it passes its title into the function.
All I want to do is hide the title of the button so you can not see the button. I have them overlaid over images which I use to show buttons. I have the text set to transparent but it still turns white when it is being clicked.
If you include code in your explanation, please explain where it should go.
After IOS7, If you want to just hide the title on titleLabel of a button you can do as follow. This way the title is still there it just makes it invisible. if you do NSLog("%#",button.currentTitle) you will see the title in terminal. Hope this helps.
[button setTitle:#"Button Title" forState:UIControlStateNormal];
button.titleLabel.layer.opacity = 0.0f;
I found only one correct working way:
//hide
yourButton.setTitleColor(UIColor.clearColor(), forState: .Normal)
//show (put your color)
yourButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
using button.titleLabel.hidden = YES will not work (at least on on iOS 7).
I ended up using:
// remove the button since hiding it doesn't work
[button.titleLabel removeFromSuperview];
// put back when you're done
[button addSubview:button.titleLabel];
You can hide the label inside the button:
button.titleLabel.hidden=YES;
or set the button's title to #"" and save the value somewhere else when you want to retrieve it.
I create a subclass of UIButton and override layoutSubviews method. Hiding titleLabel in layoutSubviews method works.
public class LoadingButton: UIButton {
public var isTitleHidden: Bool = false {
didSet {
titleLabel?.isHidden = isTitleHidden
}
}
public override func layoutSubviews() {
super.layoutSubviews()
titleLabel?.isHidden = isTitleHidden
}
}
if wanna hide titleLabel, just set isTitleHidden = true
I could not remove the title from the titleLabel nor the whole view as I needed it for constraints.
I ended up using
isEnabled = false
titleLabel?.layer.opacity = 0
setTitleColor(.clear, for: .disabled)
to hide the title and
isEnabled = true
titleLabel?.layer.opacity = 1
setTitleColor(titleColor(for: .normal), for: .disabled)
to show it again
To hide a title temporary just setTitle to empty string
setTitle("", for: .normal)
the button title label will be hidden but the title will still in the titleLabel, you can return it back using
setTitle(titleLabel?.text, for: .normal)
If you want to temporary hide the title, while you disabling the button, use:
setTitle("Title", for: .normal)
setTitle("", for: .disabled)
Then, button.isEnabled = false, when you want to hide the title.
I got a problem with title, because used an attributed title and nothing above helped. Then i found a workaround:
button.titleEdgeInsets = .init(top: 0, left: shouldHide ? 1000 : 0, bottom: 0, right: 0)
However it has some disadvantages, but fit my needs.
I've come up with this solution, which allows you to set title label text and use it with button image without showing it and not moving button image to the left.
- (void)hideButtonLabel:(UIButton*)buttonInp {
buttonInp.titleLabel.layer.opacity = 0.0f;
uttonInp.titleLabel.font = [UIFont fontWithName:#"Helvetica-Light" size:0.0];
}
You cannot hide UIButton titleLabel using .hidden property. Instead you can do this.
To Hide:
[self.yourButton setTitle:nil forState:UIControlStateNormal];
To Show:
[self.yourButton setTitle:#"Your Text" forState:UIControlStateNormal];
In Swift-
You don't need to hide nor need to make the opacity to 0.0. Swift gave you a simpler way.
Just set the title as nil. In fact, I got the idea from the documentation.
Command click on the setTitle(_:for:) method and you will see-
open func setTitle(_ title: String?, for state: UIControl.State) // default is nil. title is assumed to be single line
So, I just set it to nil.
setTitle(nil, for: .normal)
Swift 5 to hide button label:
myButton.titleLabel?.isHidden = true
Here myButton is a #IBOutlet of the button.