I'm new to Swift and I assume this is a fundamental question to programming for iOS.
I have three buttons in my storyboard and I want to customize how those buttons look if pressed once, twice and three times.
I also have three themes (pink, blue and orange). What I thought of doing is to create three new classes called pink,blue and orange.swift
I don't want to create them programmatically, only style them programmatically.
What I lack to understand is how do I call the function (Example: "ButtonIsPressed") from my pink.swift class into my #IBAction and #IBOutlet in the main view controller that is also object oriented (ie. I don't want to create a function for every button)?
I can't really find a decent and up-to-date Swift 3 Tutorial for this, any help or advice on this topic will be greatly appreciated.
Why can it not be as simple as?:
#IBAction func buttonPressed(_ sender: UIButton!) {
self.backgroundColor = myPinkCGolor
}
I think shallowThought's answer will work for changing backgroundColor based on button state of a specifically named IBOutlet.
I have three buttons in my storyboard and I want to customize how those buttons look if pressed once, twice and three times.
If you want to maintain "state", as in have a "counter" for how many times a button's been clicked or tapped, you can use the "tag" property of the button. Set it to zero, and in your IBAction functions increment it. (Like shallowThought said, use .touchUpInside and .touchDown for the events.)
Also, you have one minor - but important! - thing wrong in your code Brewski:
#IBAction func buttonPressed(_ sender: UIButton!) {
self.backgroundColor = myPinkCGolor
}
Should be:
#IBAction func buttonPressed(_ sender: UIButton!) {
sender.backgroundColor = myPinkCGolor
}
So combining everything - up vote to shallowThought (also, changing his AnyObject to UIButton and making it Swift 3.x syntax on the UIColors - and would end up with this. Note that there is no need for an IBOutlet, and you can wire everything up in IB without subclassing:
// .touchUpInside event
// can be adapted to show different color if you want, but is coded to always show white color
#IBAction func buttonClicked(sender: UIButton) {
sender.backgroundColor = UIColor.whiteColor()
}
// .touchDown event
// will show a different color based on tap counter
#IBAction func buttonReleased(sender: UIButton) {
switch sender.tag {
case 1:
sender.backgroundColor = UIColor.blue
case 2:
sender.backgroundColor = UIColor.red
case 3:
sender.backgroundColor = UIColor.green
default:
sender.backgroundColor = UIColor.yellow
}
sender.tag += 1
}
There is no methode to set the backgroundColor for a certain state, like there is for other UIButton properties, so you have to listen to the buttons actions:
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBAction func buttonClicked(sender: AnyObject) { //Touch Up Inside action
button.backgroundColor = UIColor.whiteColor()
}
#IBAction func buttonReleased(sender: AnyObject) { //Touch Down action
button.backgroundColor = UIColor.blueColor()
}
...
}
or set a unicolor image withimage:UIImage, forState:.selected.
Related
I am trying to use two buttons to toggle between an animated sliding view. When the UIView loads, I want button1 to be UIColor.darkGrey and button2 to be UIColor.lightGrey. Then, when I press button2 I want button2 to become UIColor.darkGrey and button1 to become UIColor.lightGrey. If I press button1, I want button1 to be UIColor.darkGrey and button2 to be UIColor.lightGrey.
It seems simple; Using the storyboard, I connected a UIButton for button1 and button2 as an outlet. Then I connected each as actions. In each of the actions, I included the following code:
#IBAction func button1Action(_ sender: UIButton) {
button2.titleLabel?.textColor = UIColor.lightGray
button1.titleLabel?.textColor = UIColor.darkGray
UIView.animate(withDuration: 1){
self.side1.constant = 0
self.side2.constant = 0
self.sideA.constant = 400
self.sideB.constant = -400
self.view.layoutIfNeeded()
}
}
#IBAction func button2Action(_ sender: UIButton) {
button1.titleLabel?.textColor = UIColor.lightGray
button2.titleLabel?.textColor = UIColor.darkGray
view.layoutIfNeeded()
UIView.animate(withDuration: 1){
self.side1.constant = -400
self.side2.constant = 400
self.sideA.constant = 0
self.sideB.constant = 0
self.view.layoutIfNeeded()
}
}
When I press button1, everything works as expected; However, whenever I press button2 both buttons are UIColor.lightGrey. Am I missing something obvious?
You get some methods "for free" with buttons to manage their state. One of them is isSelected. Another is the tag property, so you can figure out which button is which. Since you've only got two buttons, you can get away with just using isSelected to figure out which is which. You can also use computed vars to make your life easier. With those things in mind, here's one approach you could utilize to managing the buttons' states:
Declare a buttons computed var, like so
#IBOutlet var firstButton: UIButton!
#IBOutlet var secondButton: UIButton!
// computed var to access your buttons
private var buttons: [UIButton] {
return [firstButton, secondButton]
}
Set up your buttons in viewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
// one setup to configure each button for selected or not selected
buttons.forEach { button in
button.setTitleColor(.darkGray,
for: .selected)
button.setTitleColor(.lightGray,
for: .normal)
}
firstButton.isSelected = true
}
func setTitleColor(_ color: UIColor?, for state: UIControl.State) will remain in effect for the lifetime of the button, so you don't need to fiddle with it after the initial declaration (unless you want to change the button's behavior later).
One #IBAction for both buttons and utilize the tag property to figure out which one is which. Since you've only got two buttons, I'm just using isSelected. Here's what your single #IBAction would look like:
#IBAction func buttonAction(_ sender: UIButton) {
UIView.animate(withDuration: 1.0) {
// flip buttons
self.buttons.forEach { button in
button.isSelected.toggle()
}
if self.firstButton.isSelected {
// tweak your constraints for firstButton.isSelected == true
// tweak your constraints for secondButton.isSelected == false
} else {
// tweak your constraints for firstButton.isSelected == false
// tweak your constraints for secondButton.isSelected == true
}
}
}
Based on your current implementation, you'll need to right click on the UIButtons on storyboard and nuke the existing IBAction connections and reconnect both buttons to the method above.
I have two UIButtons that I want to use to set an A/B value to a variable before I save data to a database. I want a button to become selected when tapped, and deselected when the other button is tapped, and vice versa. What is a good solution for accomplishing this programmatically or in Interface Builder?
In order to set an "A/B value" as you mention, the easiest option would be to use a UISwitch or -in the general case of possibly more than 2 options- a UISegmentedControl (as #rmaddy suggested in the question's comments) .
These controls have built-in the "choose just one out of many" functionality that you are looking for.
The drawbacks of the switch are:
It has to be either on or off (does not support a selection state of "neither A nor B")
You can't have separate title labels for each state.
If you still want two separate UIButton instances, you can:
Have references to both buttons in your view controller (#IBOutlets wired using Interface Builder), e.g.:
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
Implement the action method for both buttons in such a way that it sets the selected state of the tapped button, and resets the other one. For example:
#IBAction func buttonAction(sender: UIButton) {
if sender == leftButton {
leftButton.isSelected = true
rightButton.isSelected = false
} else if sender == rightButton{
leftButton.isSelected = false
rightButton.isSelected = true
}
}
This is a quick-and-dirty solution for just two buttons. If you want a generic radio group of n-buttons, there are open source solutions on GitHub, etc...
Try this.
First create both button separate #IBOutlet.
#IBOutlet weak var btnYes: UIButton!
#IBOutlet weak var btnNo: UIButton!
Set Both Button Tag Like this and you also set tag using storyboard.
override func viewDidLoad() {
super.viewDidLoad()
btnYes.tag = 1
btnNo.tag = 2
}
Implement Common #IBAction method for both buttons
#IBAction func btnYesNoTapped(_ sender: UIButton) {
if sender.tag == 1 {
self.IsBtnSelected(isSelect: true, with: self.btnYes)
}else {
self.IsBtnSelected(isSelect: true, with: self.btnNo)
}
}
Create Custome Method
func IsBtnSelected(isSelect:Bool,with sender:UIButton){
self.btnYes.isSelected = false
self.btnNo.isSelected = false
sender.isSelected = isSelect
}
you can use following function for creating a radio button behaviour, you have to btn outlet to be selected and array of both outlets to this function. instead ofcolor you can also compare images and set images. for getting a required value yo can create a variable in viewcontroller and assign this variable a value in IBAction of btn and you can call this function from IBAction.
func radioButton(_ btnToBeSelected: UIButton, _ btnArray: [UIButton]) {
for btn in btnArray {
if btn == btnToBeSelected {
btn.backgroundColor = UIColor.black
//selected btn
//You can also set btn images by
//btn.setImage(<#T##image: UIImage?##UIImage?#>, for: <#T##UIControlState#>)
} else {
btn.backgroundColor = UIColor.red
//not selected btn
}
}
}
In iOS , you would have to do it manually.See the below approaches,
Use a switch . Using a UISwitch would be better if the option indicates a on/off state.
Use a same method when the button is pressed. Whenever the method gets called deselect the other button/buttons and select the pressed button. You can use tags or keep a reference of the buttons to differentiate between them.
Lastly , keep different methods for each buttons . Just deselect the other buttons whenever the button is pressed.
You can follow the above approaches by using interface builder or programmatically.
You can achieve it like below
I have implemented it for dates which are in TableView you just need to do little modifications
enum filterDateSelectableOptions:Int {
case AssignDate
case DueDate
case CompletionDate
}
//Assign Date selected by default
var currentSelectedFilterDate:filterDateSelectableOptions = .AssignDate
Now
func btnRadioButtonTapped(sender:UIButton) {
switch sender.tag {
case kTableViewRow.AssignDate.rawValue:
self.currentSelectedFilterDate = .AssignDate
case kTableViewRow.DueDate.rawValue:
self.currentSelectedFilterDate = .DueDate
case kTableViewRow.CompletionDate.rawValue :
self.currentSelectedFilterDate = .CompletionDate
default:
break;
}
//sender.isSelected = !sender.isSelected
self.tblFilterList.reloadData()
}
in cellForRow I have
// THIS IS DIFFERENT ENUM SO +1 is required in my case
case .AssignDate,.DueDate,.CompletionDate :
let button = buttonRadioCircle
button.tag = row.rawValue
cell.accessoryView = button
button.addTarget(self, action: #selector(btnRadioButtonTapped(sender:)), for: .touchUpInside)
button.isSelected = self.currentSelectedFilterDate.rawValue + 1 == row.rawValue
}
I'm a beginner of swift. I have 4 buttons in my view. I want to change selected buttons background property to show user. Could you please help me thanks.
If wanted them all to be the same color, you could connect them as an IBOutlet Collection and then iterate through them using a for in loop and setting their backgroundColor properties.
for button in buttons {
button.backgroundColor = UIColor.lightGreyColor()
}
Additionally if you wanted to set the color for states you can use these methods:
#IBAction func buttonClicked(sender: AnyObject) { //Touch Up Inside action
button.backgroundColor = UIColor.whiteColor()
}
#IBAction func buttonReleased(sender: AnyObject) { //Touch Down action
button.backgroundColor = UIColor.blueColor()
}
I have three buttons,and only one button can be chosen by the user at a time,that means that other then the initial state where none are chosen only one button can be at a highlighted state at a time.After another button (a forth one) is clicked,all the previous button's abilities to be clicked on are disabled.How do I do this?
button.enabled = false /// this will make a button disabled in swift
Why not use the 4th button to toggle a bool - that can be used to check on the state of the other buttons?
var lockedButtons: Bool = true
#IBAction func toggleButtonLock(sender: UIButton) {
lockedButtons = !lockedButtons
}
#IBAction func Button1(sender: UIButton) {
if !lockedButtons{
//Button1 code
}
}
//button 2 & 3 code similar....
Basically, I have a three buttons on my main screen.
When I select one of these buttons, I would like the text on the selected button to change to bold and change color (blue).
When I select a different button, I would like the newly selected button to change to bold and change color(blue), and the previously selected button to go back to normal. (non-bold and black text)
I have these buttons sending an action to the script.
This is what I have, I can't seem to get it to work. Help would be much appreciated!
#IBAction func buttonOne(sender: UIButton){
sender.setTitleColor(UIColor.blueColor(), forState: UIControlState.Highlighted)
}
I have tried .Highlighted and .Selected on the UIControlState, neither seem to work. I have also tried the following, but I cant get it to work.
#IBAction func buttonOne(sender: UIButton){
sender.titleLabel?.textColor = UIColor.blueColor()
}
I figured that since the sender was a UIButton, and it was the button that was clicked, taking the values off of it and resetting them would work. I do believe I am missing something.
Thank you
Sounds like you want UIControlState.Normal
Selected does nothing in most cases, and Highlighted is only while you're pressing the button.
See more info here: https://developer.apple.com/library/ios/documentation/uikit/reference/uicontrol_class/index.html#//apple_ref/doc/constant_group/Control_State
Maybe you can do with a transform...
#IBAction func buttonPressed(sender: UIButton) {
sender.titleLabel!.textColor = UIColor.blueColor()
sender.transform = CGAffineTransformMakeScale(0.8, 0.8)
}
#IBAction func buttonReleased(sender: UIButton) {
sender.titleLabel!.textColor = UIColor.redColor()
sender.transform = CGAffineTransformIdentity
}
Provide tags to all buttons, connect each button actions to same function and try the following code:
#IBAction func butnClicked (sender : UIButton) {
for tg in 1...2 {
print(sender.tag)
let tmpButton = self.view.viewWithTag(tg) as? UIButton
if tmpButton?.tag == sender.tag {
tmpButton?.setTitleColor(.red, for: .normal)
} else {
tmpButton?.setTitleColor(.gray, for: .normal)
}
}
Hope will be helping.