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.
Related
I have a CollectionView and a Button inside of an UIView. The purpose of the button is change the theme of the app, and I can change all colors, except for the backgroundColor of a nameContainerView on my TatodexCell (a custom cell).
I can't figure out how to access that property, and then, change the color I want.
THE FOLLOWING CODE IS LOCATED ON MY TatodexController FILE
My button property is:
let buttonChangeTheme: UIButton? = {
let button = UIButton()
button.setTitle("Change to blue theme", for: .normal)
button.addTarget(self, action: #selector(themeButtonClicked), for: .touchUpInside)
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.layer.borderWidth = 3
button.layer.borderColor = Colors.mainBlack?.cgColor
button.backgroundColor = Colors.darkBlue
button.tintColor = Colors.mainWhite
return button
}()
My button-func is this one:
#objc func themeButtonClicked() {
clickCheck = !clickCheck
if clickCheck {
navigationController?.navigationBar.barTintColor = Colors.lightBlue
collectionViewPokemon?.backgroundColor = Colors.darkBlue
buttonChangeTheme?.backgroundColor = Colors.darkRed
buttonChangeTheme?.setTitle("Return to red theme", for: .normal)
}
else {
navigationController?.navigationBar.barTintColor = Colors.lightRed
collectionViewPokemon?.backgroundColor = Colors.darkRed
buttonChangeTheme?.backgroundColor = Colors.darkBlue
buttonChangeTheme?.setTitle("Change to blue theme", for: .normal)
}
}
THE FOLLOWING CODE IS LOCATED ON MY TatodexCell FILE
The nameContainerView I wanna modify it's bg color is:
lazy var nameContainerView: UIView = {
let nameView = UIView()
nameView.backgroundColor = Colors.lightRed
nameView.addSubview(nameLabel)
nameLabel.center(inView: nameView)
return nameView
}()
My goal is to change nameView.backgroundColor = Colors.lightRed to nameView.backgroundColor = Colors.lightBlue, but I can't access that property.
I would really appreciate any help or advice. Perhaps the solution is hiding in plain sight, but I've tried many ways and none of them worked. Let me know if another chunk of code is needed to be shown.
If you implement the tintColorDidChange() method in your custom collection view cell, and in that method, you set the cell's background color to the tint color, then when you change the owning UICollectionView's tint color, the cells's tintColorDidChange() methods will fire and you'll see the change.
Hello, I have provided the link above to show a visual view of what I am trying to accomplish. So each button is a segue to the next view except the last button is not which is intended. The last two views with the back buttons at the top that are automatically included because of the nav controller I want to have those back buttons go to the first view controller. How can I do this either with xcode and swift?
If you want to remove all the navigation controller then use this code
Put this code in the button selector method
self.navigationController!.viewControllers.removeAll()
OR
navigationController?.popToRootViewController(animated: true)
OR
If you don’t have a Navigation Controller and use dismissViewController method, you still can use:
view.window?.rootViewController?.dismiss(animated: true, completion: nil)
Now comes the back button code:
override func viewDidLoad() {
super.viewDidLoad()
var backbutton = UIButton(type: .Custom)
backbutton.setImage(UIImage(named: "BackButton.png"), forState: .Normal) // Any image can be used. download back button image from any site or whatever you wanna use.
backbutton.setTitle("Back", forState: .Normal)
backbutton.setTitleColor(backbutton.tintColor, forState: .Normal) // You can change the TitleColor
backbutton.addTarget(self, action: "backAction", forControlEvents: .TouchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
//here put code from above whichever you wanna use for example I'm using one
self.navigationController?.popToRootViewController(animated: true)
}
I've examined many GitHub and StackOverflow solutions to creating a raised center tab bar button and tried multiple times into creating one but I always end of right back to square one.
So below are the steps of what I've been doing, if someone can solve the problem it would be greatly appreciated.
Created a Tab Bar Controller to navigate to 5 different View Controllers
Created a Custom Class for the Tab Bar Controller called CustomTabBarController
Inside my CustomTabBarController File is
import UIKit
class CustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setupMiddleButton()
}
func setupMiddleButton() {
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height:64))
var menuButtomFrame = menuButton.frame
menuButtomFrame.origin.y = view.bounds.height - menuButtomFrame.height
menuButtomFrame.origin.x = view.bounds.width/2 - menuButtomFrame.size.width/2
menuButton.frame = menuButtomFrame
view.addSubview(menuButton)
menuButton.setImage(UIImage(named: "MidPhoto"), for: .normal)
menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)
view.layoutIfNeeded()
tabBarController?.tabBar.addSubview(menuButton)
}
#objc private func menuButtonAction(sender: UIButton) {
selectedIndex = 2
}
}
That's it. I only edited 1 file (CustomTabBarController) and it works but the image is appearing into unwanted View Controllers and I've done multiple things like: Hide Bottom Bar On Push, self.tabBarController?.tabbar.isHidden = true, and so on.
What can I do to fix this?
let btnName = UIButton()
btnName.setImage(UIImage(named: "backIcon"), for: .normal)
btnName.addTarget(self, action: #selector(AddContactViewController.backAction), for: .touchUpInside)
let leftBarButton = UIBarButtonItem()
leftBarButton.customView = btnName
self.navigationItem.leftBarButtonItem = leftBarButton
It works fine, it does what is intended to do. However, on the navigation item it's invisible. But when I click on the area where it should be. It works.
Actually you may have two navigation bars one is of your current class and another is of your previous class.So, you can try by adding below code in your previous class.
override func viewWillDisappear(_ animated: Bool) {
self.navigationController!.navigationBar.isHidden = true
}
I also faced the same problem and it worked for me. May be it will help you.
Everything is ok, except you forgot to set the frame for your button, that's why it's not being shown.
let btnName = UIButton(frame: CGRect(x: 0, y: 0, width: 18, height: 17))
btnName.setImage(UIImage(named: "backIcon"), for: .normal)
btnName.addTarget(self, action: #selector(AddContactViewController.backAction), for: .touchUpInside)
let leftBarButton = UIBarButtonItem()
leftBarButton.customView = btnName
self.navigationItem.leftBarButtonItem = leftBarButton
Rather than hard-coding some frame values, you are better off calling the sizeToFit() method after setting the image, title, etc. I hit this problem today where a custom back button was showing OK on iOS11, but was not visible on iOS9.
btnName.sizeToFit()
I wonder how I get my border around my UIButton to change opacity together with the text inside it, when it is either clicked or highlighted.
My logic tells me, that it should be something like this.. but it doesn't seem to work:
//BTN STYLING
btnstd.layer.cornerRadius = 5
btnstd.layer.borderWidth = 1.5
btnstd.layer.borderColor = UIColor.white.cgColor
//Change bordercolor when highlighted
if(btnstd.isHighlighted) {
btnstd.layer.borderColor = UIColor(white:1,alpha:0.3).cgColor
}
This is by the way put inside my ViewDidLoad() function
The actions you are looking for are .touchDown and anything .touchUp:
override func viewDidLoad() {
super.viewDidLoad()
theButton.setTitle("Normal", for: .normal)
theButton.setTitle("Highlighted", for: .highlighted)
theButton.layer.borderColor = UIColor.red.cgColor
theButton.layer.borderWidth = 1
theButton.addTarget(self, action: #selector(startHighlight), for: .touchDown)
theButton.addTarget(self, action: #selector(stopHighlight), for: .touchUpInside)
theButton.addTarget(self, action: #selector(stopHighlight), for: .touchUpOutside)
}
func startHighlight(sender: UIButton) {
theButton.layer.borderColor = UIColor.green.cgColor
theButton.layer.borderWidth = 1
}
func stopHighlight(sender: UIButton) {
theButton.layer.borderColor = UIColor.red.cgColor
theButton.layer.borderWidth = 1
}
It depends on what you are trying to do.
Case #1: You want this change to happen when the button is highlighted, but in a normal state have a different set of properties.
let theButton = UIButton()
// set common properties and layout code
theButton.setTitle("Normal", for: .normal)
theButton.setTitle("Highlighted", for: .highlighted)
In addition, you have setTitleColor(), setAttributedTitle, setTitleShadowColor(), setImage(), and setBackgroundImage() that you can code directly.
Border color in this case would need a subclass (not an extension, you want public properties) where you will check self.layer.hitTest() after wiring up a tap gesture on self.
Case #2: You want the button state to change when clicked, and stay changed.
You are part way there. If you supply the button in IB, make sure you add an IBAction for event touchUpInside. If you are working in code, here's the Swift 3 syntax.
theButton.addTarget(self, action: #selector(changeButton), for: .touchUpInside)
func changeButton(sender: UIButton) {
sender.setTitle("New Title", for: .normal)
sender.layer.borderColor = UIColor.red.cgColor
}
My preference (but only that) is to more strongly-type the sender (I think that's the correct term) for my actions. I'm sure there are pros and cons for using a specific sender (like UIButton) over AnyObject, but in this case I think the biggest reason is you don't need to force-cast the sender to UIButton.