Hey I'm new in iOS Development, I have a problem to make two button selected and unselected state and then store value of a gender. I want when user choose gender the other gender will be disable. Can anyone help me?
My button code
let menButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Men", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .yellow
button.isSelected = false
button.isEnable = true
button.addTarget(self, action: #selector(handlePickGender), for: .touchUpInside
return button
}()
let womenButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Women", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .blue
button.isSelected = false
button.isEnable = true
button.addTarget(self, action: #selector(handlePickGender), for: .touchUpInside
return button
}()
try this:
#objc func handlePickGender(sender: UIButton) {
menButton.setTitleColor(UIColor.yellow, for: .normal)
womenButton.setTitleColor(UIColor.yellow, for: .normal)
sender.setTitleColor(UIColor.blue, for: .normal)
//store gender
let selectedGender = sender.title(for: .normal)
}
First, create enum for Gender and add the Male and Female as the cases for that enum.
enum Gender {
case male
case female
}
Have the switch for toggling the UIButton states.
func chooseGender(_ gender: Gender) {
switch gender {
case .male:
// code for select and unselect
case .female:
// code for select and unselect
}
}
From the UIButton, use the isEnabled property for enable and disable.
If you are trying to create toggle buttons.
you can set button image for state.
button.setImage(UIImage(named: "unselected"), for: .normal)
button.setImage(UIImage(named: "selected"), for: .selected)
#IBAction func buttonPressed(sender: UIButton) {
button.selected = !button.selected
}
OR you can set background color for button
#IBAction func buttonPressed(sender: UIButton) {
button.selected = !button.selected
if button.selected {
button.backgroundColor = .blue
} else {
button.backgroundColor = .clear
}
}
Related
I'm trying to use a switch statement on a three button action where the user can select between morning, afternoon and evening times. I'm wanting to change the background and text colors based on what button is selected.
Right now my buttons are not changing based on tap, what do I need to do in order to get this working? Also, how can I use like tag 10 and tag 20 in one of the cases? Thank you.
// My Buttons
private lazy var morningButton: TimeButton = {
let button = TimeButton(type: .system)
button.setTitle("Morning", for: .normal)
button.titleLabel?.font = UIFont(name: "AvenirNext-Medium", size: 14)
return button
}()
private lazy var afternoonButton: TimeButton = {
let button = TimeButton(type: .system)
button.setTitle("Afternoon", for: .normal)
button.titleLabel?.font = UIFont(name: "AvenirNext-Medium", size: 14)
return button
}()
private lazy var eveningButton: TimeButton = {
let button = TimeButton(type: .system)
button.setTitle("Evening", for: .normal)
button.titleLabel?.font = UIFont(name: "AvenirNext-Medium", size: 14)
return button
}()
// Switch Statement
#objc func timeButtonsTapped(_ sender: TimeButton) {
switch sender.tag {
case 10:
morningButton.backgroundColor = .darkPurpleTint
morningButton.setTitleColor(.white, for: .normal)
afternoonButton.backgroundColor = .white
afternoonButton.setTitleColor(.darkPurpleTint, for: .normal)
eveningButton.backgroundColor = .white
eveningButton.setTitleColor(.darkPurpleTint, for: .normal)
case 20:
afternoonButton.backgroundColor = .darkPurpleTint
afternoonButton.setTitleColor(.white, for: .normal)
morningButton.backgroundColor = .white
morningButton.setTitleColor(.darkPurpleTint, for: .normal)
eveningButton.backgroundColor = .white
eveningButton.setTitleColor(.darkPurpleTint, for: .normal)
case 30:
eveningButton.backgroundColor = .darkPurpleTint
eveningButton.setTitleColor(.white, for: .normal)
morningButton.backgroundColor = .white
morningButton.setTitleColor(.darkPurpleTint, for: .normal)
afternoonButton.backgroundColor = .white
afternoonButton.setTitleColor(.darkPurpleTint, for: .normal)
case 10 & 20:
morningButton.backgroundColor = .darkPurpleTint
morningButton.setTitleColor(.white, for: .normal)
afternoonButton.backgroundColor = .darkPurpleTint
afternoonButton.setTitleColor(.white, for: .normal)
eveningButton.backgroundColor = .white
eveningButton.setTitleColor(.darkPurpleTint, for: .normal)
case 10 & 30:
morningButton.backgroundColor = .darkPurpleTint
morningButton.setTitleColor(.white, for: .normal)
eveningButton.backgroundColor = .darkPurpleTint
eveningButton.setTitleColor(.white, for: .normal)
afternoonButton.backgroundColor = .white
afternoonButton.setTitleColor(.darkPurpleTint, for: .normal)
case 20 & 30:
afternoonButton.backgroundColor = .darkPurpleTint
afternoonButton.setTitleColor(.white, for: .normal)
eveningButton.backgroundColor = .darkPurpleTint
eveningButton.setTitleColor(.white, for: .normal)
morningButton.backgroundColor = .white
morningButton.setTitleColor(.darkPurpleTint, for: .normal)
case 10 & 20 & 30:
morningButton.backgroundColor = .darkPurpleTint
morningButton.setTitleColor(.white, for: .normal)
afternoonButton.backgroundColor = .darkPurpleTint
afternoonButton.setTitleColor(.white, for: .normal)
eveningButton.backgroundColor = .darkPurpleTint
eveningButton.setTitleColor(.white, for: .normal)
default:
morningButton.backgroundColor = .white
morningButton.setTitleColor(.darkPurpleTint, for: .normal)
afternoonButton.backgroundColor = .white
afternoonButton.setTitleColor(.darkPurpleTint, for: .normal)
eveningButton.backgroundColor = .white
eveningButton.setTitleColor(.darkPurpleTint, for: .normal)
}
}
// My Function
fileprivate func configureUI() {
morningButton.tag = 10
morningButton.isUserInteractionEnabled = true
afternoonButton.tag = 20
afternoonButton.isUserInteractionEnabled = true
eveningButton.tag = 30
eveningButton.isUserInteractionEnabled = true
morningButton.addTarget(self, action: #selector(timeButtonsTapped(_:)), for: .touchUpInside)
afternoonButton.addTarget(self, action: #selector(timeButtonsTapped(_:)), for: .touchUpInside)
eveningButton.addTarget(self, action: #selector(timeButtonsTapped(_:)), for: .touchUpInside)
}
You don't need to spread the button coloring logic all over your view controller. It results in lots of code duplication and poor maintainability in the future.
The UIButton has an isSelected property, you can use it in this particular case to save the state of a button. Also I would suggest moving all of the colors into the button's subclass so that the client doesn't have to worry about them. The button should be responsible for switching its colors.
Here's what the TimeButton class would look like:
class TimeButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
override var isSelected: Bool {
didSet {
updateBackgroundColor()
}
}
// MARK: - Private
private func setup() {
translatesAutoresizingMaskIntoConstraints = false
setTitleColor(.white, for: .normal)
setTitleColor(.systemPurple, for: .selected)
titleLabel?.font = UIFont(name: "AvenirNext-Medium", size: 14)
updateBackgroundColor()
}
private func updateBackgroundColor() {
backgroundColor = isSelected ? .white : .systemPurple
}
}
Your view controller now should look like this:
class ViewController: UIViewController {
private lazy var morningButton: TimeButton = {
let button = TimeButton(type: .custom)
button.setTitle("Morning", for: .normal)
button.addTarget(self, action: #selector(didSelectButton(_:)), for: .touchUpInside)
return button
}()
private lazy var afternoonButton: TimeButton = {
let button = TimeButton(type: .custom)
button.setTitle("Afternoon", for: .normal)
button.addTarget(self, action: #selector(didSelectButton(_:)), for: .touchUpInside)
return button
}()
private lazy var eveningButton: TimeButton = {
let button = TimeButton(type: .custom)
button.setTitle("Evening", for: .normal)
button.addTarget(self, action: #selector(didSelectButton(_:)), for: .touchUpInside)
return button
}()
#objc private func didSelectButton(_ button: TimeButton) {
button.isSelected = !button.isSelected
// do some additional stuff if needed
}
}
Note the type: .custom in the button's init - this will disable the default button styling when it gets selected.
If you want to get the value of some button - just refer to its isSelected property:
let shouldUseMorningTime = morningButton.isSelected
I read some articles but didn't find a solution that solved my problem. Currently im building an iOS app in Swift 3. I placed a UIButton called registerButton into my view. If someone touches the button a new ViewController shall appear(newController). Beside that the color of the registerButton.textlabel.setColor() should be changed when a user touches the button and hold it pressed ? The presentation of the newController works but not the change color of the textLabel. Im changing the color of the registerButton in the Registration function. Has someone an idea ? Thanks
var registerButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Registration", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.addTarget(self, action: #selector(registration), for: .touchUpInside) // Action
return button
}()
func registration(){
let color = UIColor(r: 255, g: 0, b: 102)// red
registerButton.setTitleColor(color, for: .highlighted)
let newController = ViewController()
present(newController, animated: true, completion: nil)
}
Button normal
Button pressed no red text label
var registerButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Registration", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.addTarget(self, action: #selector(colorChange), for: .touchDown)
button.setTitleColor(.red, for: .highlighted)
// Action
return button
}()
This should work just fine
Try to change the color for the state Focused when you are creating the button, not when pressed.
var registerButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Registration", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.setTitleColor(UIColor.red, for: .focused)
button.addTarget(self, action: #selector(registration), for: .touchUpInside) // Action
return button
}()
I'm looking to implement a button that can be used as a tickbox and enablers the user to toggle the tickbox in an on/off fashion (unticked/ticked). Currently I've set up my button using the attributes inspector including the 'Title' as "X" and the 'Text Color' is red.
Once loaded the button appears a red "X", once tapped it turns to a green tick.
My question is... how do you enable the button to be tapped again to revert back to the red X (it's original state), an continue in a loop whenever tapped?
#IBAction func check2(_ sender: UIButton) {
sender.setTitle("✓", for: .normal)
sender.setTitleColor(UIColor.green, for: UIControlState.normal)
}
Thank you
Track the state with a variable and update the appearance based on the state:
class ViewController: UIViewController{
#IBOutlet weak var button: UIButton!
var isChecked = true
#IBAction func check2(_ sender: UIButton) {
isChecked = !isChecked
if isChecked {
sender.setTitle("✓", for: .normal)
sender.setTitleColor(.green, for: .normal)
} else {
sender.setTitle("X", for: .normal)
sender.setTitleColor(.red, for: .normal)
}
}
}
Updated for Swift 3
lazy var toggleBT: UIButton = {
let button = UIButton()
button.frame = CGRect(x: 40, y: 100, width: 200, height: 40)
button.backgroundColor = .orange
button.isSelected = false // optional(because by default sender.isSelected is false)
button.setTitle("OFF", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 14)
button.addTarget(self, action: #selector(handleToggleBT), for: .touchUpInside)
return button
}()
func handleToggleBT(sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
print(sender.isSelected)
toggleBT.setTitle("ON", for: .normal)
}
else {
print(sender.isSelected)
toggleBT.setTitle("OFF", for: .normal)
}
} // don't forget to add this button as a subView for eg. view.addSubview(toggleBT)
Updated code for swift5
#IBAction func check2(_ sender: UIButton) {
sender.isSelected = !sender.isSelected //By default sender.isSelected is false
if sender.isSelected {
sender.setTitle("✓", for: .normal)
sender.setTitleColor(UIColor.green, for: .normal)
} else {
sender.setTitle("x", for: .normal)
sender.setTitleColor(UIColor.red, for: .normal)
}
}
I was able to create a UIBarButton item that can go back programmatically using the following code:
func backAction() -> Void {
self.navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "backAction")
self.navigationItem.leftBarButtonItem = backButton
}
The problem is that the back button doesn't have the left pointing arrow:
Is there a way to make it look like a regular back button with the arrow like this:
I would also like to know if there is a way to make the button title names as the title of the previous view controller, if that's possible.
Thanks
Below is the code by using UIButton with image you can add it as a customView for UIBarButtonItem
override func viewDidLoad() {
super.viewDidLoad()
var backbutton = UIButton(type: .Custom)
backbutton.setImage(UIImage(named: "BackButton.png"), forState: .Normal) // Image can be downloaded from here below link
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 {
self.navigationController?.popViewControllerAnimated(true)
}
Download Link
For setting the title of backbutton with the previous view controller title you have to pass the Title as a String while presenting the controller make change to above code as
var titleStrFromPreviousController: String // This value has to be set from previous controller while presenting modal controller
backbutton.setTitle(titleStrFromPreviousController, forState: .Normal)
This may help.
Swift 3
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func backAction(_ sender: UIButton) {
let _ = self.navigationController?.popViewController(animated: true)
}
Updated for Swift 4.2 - thanks to sam bing and silentbeep
Made some modifications on some colors and action's selector.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
self.navigationItem.title = title
self.navigationController?.navigationBar.barTintColor = .white
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: makeBackButton())
}
func makeBackButton() -> UIButton {
let backButtonImage = UIImage(named: "backbutton")?.withRenderingMode(.alwaysTemplate)
let backButton = UIButton(type: .custom)
backButton.setImage(backButtonImage, for: .normal)
backButton.tintColor = .blue
backButton.setTitle(" Back", for: .normal)
backButton.setTitleColor(.blue, for: .normal)
backButton.addTarget(self, action: #selector(self.backButtonPressed), for: .touchUpInside)
return backButton
}
#objc func backButtonPressed() {
dismiss(animated: true, completion: nil)
// navigationController?.popViewController(animated: true)
}
You can do by embedding your view in a navigation controller.
Here is an image showing how to do that:
Hope it helps :D
For future searches, I wanted to add that you can now use the default icon by this code:
override public func viewDidLoad() {
// create chevron image
let config = UIImage.SymbolConfiguration(pointSize: 25.0, weight: .medium, scale: .medium)
let image = UIImage(systemName: "chevron.left", withConfiguration: config)
// create back button
let backButton = UIButton(type: .custom)
backButton.addTarget(self, action: #selector(self.close(_:)), for: .touchUpInside)
backButton.setImage(image, for: .normal)
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func close(_ sender: UIButton) {
self.navigationController?.dismiss(animated: true, completion: nil)
}
The first answer works great however the image is a bit too big so use the preview and scale it down to width:13 and height: 22, also set its rendering mode to .alwaysTemplate and change the UIButton's tint to white, while also adding two spaces before the string : " Back". This will result in something that is quiet similar to the navigation bar back button, the image could be better in terms of size and placement.
Edited code:
func addBackButton() {
let backButtonImage = UIImage(named: "BackButton.png")?.withRenderingMode(.alwaysTemplate)
let backButton = UIButton(type: .custom)
backButton.setImage(backButtonImage, for: .normal)
backButton.tintColor = .white
backButton.setTitle(" Back", for: .normal)
backButton.setTitleColor(.white, for: .normal)
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
I changed one last line of code from selected answer and it works for me.
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func backAction(_ sender: UIButton) {
let _ = self.dismiss(animated: true, completion: nil)
}
Swift 5
override func viewDidLoad() {
super.viewDidLoad()
let backbutton = UIButton(type: .custom)
backbutton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backbutton.setTitle("Back", for: .normal)
backbutton.setTitleColor(backbutton.tintColor, for: .normal) // You can change the TitleColor
backbutton.addTarget(self, action: Selector(("backAction")), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
self.navigationController?.popViewController(animated: true)
}
I'd like my button to remain highlighted after the user taps it. If the user taps the button again I'd like it to become de-selected/unhighlighted. I'm not sure how to go about doing this in swift. I'm currently setting the button highlight image and selected image to the same .png using interface builder.
When I run the app and tap the button, it changes to my highlight image for as long as my finger remains on the button.
Use below code
declare isHighLighted as instance variable
//write this in your class
var isHighLighted:Bool = false
override func viewDidLoad() {
let button = UIButton(type: .system)
button.setTitle("Your title", forState: UIControlState.Normal)
button.frame = CGRectMake(0, 0, 100, 44)
self.view.addSubview(button as UIView)
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonClicked(sender:UIButton)
{
dispatch_async(dispatch_get_main_queue(), {
if isHighLighted == false{
sender.highlighted = true;
isHighLighted = true
}else{
sender.highlighted = false;
isHighLighted = false
}
});
}
I would recomend to use selected state instead of highlighted the below code demonstarate with selected state
override func viewDidLoad() {
let button = UIButton(type: .system)
button.setTitle("Your title", forState: UIControlState.Normal)
button.frame = CGRectMake(0, 0, 100, 44)
self.view.addSubview(button as UIView)
//set normal image
button.setImage(normalImage, forState: UIControlState.Normal)
//set highlighted image
button.setImage(selectedImage, forState: UIControlState.Selected)
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonClicked(sender:UIButton)
{
sender.selected = !sender.selected;
}
func buttonPressed(_ sender: UIButton) {
// "button" is a property
if button.isSelected {
button.setImage(UIImage(named: "filled-heart"), for: .normal)
button.isSelected = false
}else {
button.setImage(UIImage(named: "empty-heart"), for: .selected)
button.isSelected = true
}
}
func highlightButton(button: UIButton) {
button.highlighted = true
}
#IBAction func touched(sender: UIButton) {
let timer = NSTimer.scheduledTimerWithTimeInterval(0.0, target: self, selector: Selector("highlightButton(sender)"), userInfo: nil, repeats: true)
}
this one worked fine for me!
func buttonColorChanger(sender : UIButton ) {
if button.isSelected == false
{
button.backgroundColor = UIColor.purple
print("selected")
button.setTitle("selected", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.isSelected = true
}else{
button.backgroundColor = UIColor.white
print("unselected")
button.isSelected = false
}
}
Swift 5:
#IBAction func toggleButton(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
}