how to change bordercolor when Button.isHighlighted - swift

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.

Related

Swift UIButton titleColor change when highlighted?

I would like to titleColor of my UIBUtton to change when the user taps on the button, with the below code currently the color of the UIBUtton title changes if the user press and hold on the button, however, not when tapped quickly, could you please let me know what do I need to change in the below code to make the titleColor change upon a tap detection only:
var resetFiltersButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Clear Filters", for: .normal)
button.titleLabel?.font = UIFont(name: "AppleSDGothicNeo-Bold", size: 20)
button.setTitleColor(.blue, for: .normal)
button.setTitleColor(.red, for: .highlighted)
button.titleLabel?.numberOfLines = 1
button.tag = 1
button.addTarget(self, action: #selector(buttonPressed(_:)), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
#objc func buttonPressed(_ sender: UIButton) {
// MARK: - Clear Filters button pressed:
if sender.tag == 1 {
}
}
Why don't you try implementing that inside the buttonPressed function?
#objc func buttonPressed(_ sender: UIButton) {
sender.setTitleColor(color: UIColorUI, for: UIControl.State)
}
This issue is that you are using setTitleColor for .normal and .highlighted states.
.normal is when the button is not clicked.
.highlighted is while the button is being clicked on.
Instead you could:
Just updated the .normal color when pressed (in buttonPressed); or
setTitleColor for .selected for after it's clicked and handle the selection state within buttonPressed (add sender.isSelected = !sender.IsSelected)

Use UINavigationBar appearance "back" icon for custom button?

I need to achieve a custom navigation bar's "< back" button as seen in the push segue, but on a modal.
I want to avoid too much hard-coding and found out about the property UINavigationBar.appearance().backIndicatorImage and UINavigationBar.appearance().backIndicatorTransitionMaskImage.
I want to use these to put my own text beside them for my button, since using a .png doesn't look as natural as the real thing.
I tried this but the UIImage from those properties returns as nil.
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UINavigationBar.appearance().backIndicatorImage, for: .normal)
backButton.imageView?.contentMode = .scaleAspectFit
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
UINavigationBar.appearance().backIndicatorImage is an optional value, therefore you won't be able to get the system default chevron from this. Rather, the system will use the image provided here if not null, otherwise revert to the system default.
If targeting iOS 13+, you can make use of Apple's SF Symbols, in particular the back button icon is referred to as chevron.left. To use this, call UIImage(systemName: "chevron.left"). For earlier versions of iOS, you'll have to use an image set asset. You could target all versions of iOS using if #available(iOS 13.0, *) { ... } else { ... }, where you display the system image if on iOS 13+ for improved UI appearance.
func addBackButton() {
let backButton = UIButton(type: .custom)
if #available(iOS 13.0, *) {
backButton.setImage(UIImage(systemName: "chevron.left"), for: .normal)
}
else {
backButton.setImage(UIImage(named: "backChevon"), for: .normal)
}
backButton.imageView?.contentMode = .scaleAspectFit
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}

Xcode / Swift | Knowing if a UISwitch is turned on at any time

Basically, what we got right now is a button that changes its colors (gray & green) based on if the TextFields are filled out or not... Now I would like to add a switch that also has to be switched on to let the button color change to green and change back to gray if not.
How exactly do I implement this part?
PS: setupAddTargetIsNotEmptyTextFields() is called within the viewDidLoad()
func setupAddTargetIsNotEmptyTextFields() {
self.textField_username.addTarget(self, action: #selector(textFieldsIsNotEmpty), for: .editingChanged)
self.textField_eMail.addTarget(self, action: #selector(textFieldsIsNotEmpty),
for: .editingChanged)
self.textField_password.addTarget(self, action: #selector(textFieldsIsNotEmpty), for: .editingChanged)
self.textField_confirmPassword.addTarget(self, action: #selector(textFieldsIsNotEmpty),
for: .editingChanged)
}
#objc func textFieldsIsNotEmpty(sender: UITextField) {
sender.text = sender.text?.trimmingCharacters(in: .whitespaces)
guard
let username = self.textField_username.text, !username.isEmpty,
let eMail = self.textField_eMail.text, !eMail.isEmpty,
let password = self.textField_password.text, !password.isEmpty,
let confirmPassword = self.textField_confirmPassword.text,
password == confirmPassword
else
{
//button is gray
self.button_register.backgroundColor = UIColor(red:0.20, green:0.29, blue:0.37, alpha:1.0)
return
}
//button is green
self.button_register.backgroundColor = UIColor(red:0.10, green:0.74, blue:0.61, alpha:1.0)
}
When I just add the switch to the list, I first type in everything in the textFields and then enable the switch. At this moment the button is still gray. Then I have to first change something again in the textfields to make it work.
It sounds like what's happening is that the switch isn't set to trigger the textFieldsIsNotEmpty action the way the text fields are. You can fix that easily enough: just configure the switch to call the action too:
func setupAddTargetIsNotEmptyTextFields() {
self.textField_username.addTarget(self, action: #selector(textFieldsIsNotEmpty), for: .editingChanged)
// ...yada yada yada...
self.switch_selfDestructEnable.addTarget(self, action: #selector(textFieldsIsNotEmpty), for: .valueChanged)
}
Now the switch will send a textFieldsIsNotEmpty when it's value changes just like the text fields do. Next, modify textFieldsIsNotEmpty() to check the state of the switch along with the state of the various text fields, and you should get the behavior you want.

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.

Changing color of button text and state

I need to change the color of my button's text.
I also need to change the state to Disabled after the user presses it.
I have no idea how to do this. I've been looking things up for a while but they're all either in objective C or I can't understand it (usually help docs, they're stupid.).
In swift you change color for a specific State with the setTitleColor method.
In you case it will be :
button.setTitleColor(UIColor.grayColor, forState: UIControlState.Normal)
Swift 5 Update:
button.setTitleColor(UIColor.grayColor, for: UIControl.State.normal)
To change color of text
button.titleLabel.textColor = UIColor.grayColor()
To change state, on button press add following -
button.enabled = true
IBAction method should be like -
#IBAction func buttonTapped(sender : UIButton!) {
sender.enabled = false
}
Swift 3
button.setTitleColor(UIColor.gray, for: UIControlState.normal)
Note that;
grayColor has been renamed to gray
Normal is now normal (lowercase)
You have to set the text colour for the specific button state.
For Swift3, try below code :
#IBAction func butnClicked(sender : UIButton) {
sender.setTitleColor(.red, for: .normal)
sender.isEnabled = false
}
Set Enabled and text color from story board.