i have 3 buttons that all have an image and action. However when the centerButton is pressed they should all change action and image. What is the easiest way to do this?
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
#IBOutlet weak var centerButton: UIButton!
override func draw(_ rect: CGRect) {
// Drawing code
centerButton.backgroundColor = UIColor(rgba: "#4834B4")
centerButton.layer.cornerRadius = self.centerButton.frame.width / 2
centerButton.addTarget(self, action: #selector(centerButtonClicked), for: UIControlEvents.touchUpInside)
leftButton.addTarget(self, action: #selector(rightButtonClicked), for: UIControlEvents.touchUpInside)
rightButton.addTarget(self, action: #selector(rightButtonClicked), for: UIControlEvents.touchUpInside)
}
func centerButtonClicked() {
if !pictureTaken {
//change action
} else {
//change action
}
}
If I have known well you want something like this:
func leftButtonClicked() {
if centerButton.backgroundColor == UIColor.yellowColor() {
centerButton.setBackgroundImage(image, forState: .Normal)
} else {
rightButton.setBackgroundImage(image, forState: .Normal)
}
}
func centerButtonClicked() {
if leftButton.backgroundColor == UIColor.yellowColor() {
leftButton.setBackgroundImage(image, forState: .Normal)
} else {
rightButton.setBackgroundImage(image, forState: .Normal)
}
I write two actions with an image changement.
Related
NOTE: Others have asked a similar question and none of the answers provided solved my problem.
Here's my code:
#IBOutlet var testButton:UIButton!
override func viewDidLoad() {
self.testButton.setImage(UIImage(named: "icn_checkbox_")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
self.testButton.setImage(UIImage(named: "icn_checked")?.imageWithColor(color: CMStyle.darkBlueColor), for: .selected)
}
#IBAction func testButtonAction(_ sender: Any) {
print("INSIDE testButtonAction")
self.testButton.isSelected = !self.testButton.isSelected
print("self.testButton.isSelected: ",self.testButton.isSelected)
}
This is the button:
.
These are the characteristics of the button:
.
This is icn_checkbox_ image used for .normal state:
This is icn_checked image used for .selected state:
The code inside testButtonAction gets executed. So I don't really see why wouldn't the image change (Why doesn't the button become checked).
You can use this:
#IBOutlet var testButton: UIButton!
override func viewDidLoad() {
self.testButton.setImage(UIImage(named: "icn_checkbox_")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
}
#IBAction func testButtonAction(_ sender: Any) {
print("INSIDE testButtonAction")
self.testButton.isSelected = !self.testButton.isSelected
if self.testButton.isSelected {
self.testButton.setImage(UIImage(named: "icn_checked")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
} else {
self.testButton.setImage(UIImage(named: "icn_checkbox_")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
}
}
You can set images for button states just in Storyboard, where Default = .normal and Selected = .selected
Choose selected and set image there. Image with color is similar to tintColor if You're using template images
I am facing issue in adding target action to a UIButton created in a custom UIView class.
Please look into this code for explanation-
public class ReActivateSubscriptionView: UIView {
#IBOutlet weak var reActiveSubscriptionLabel: UILabel!
#IBOutlet weak var activateNowButton: UIButton!
#IBOutlet weak var collapseSubscribeViewButton: UIButton!
var viewModel: ReActivateSubscriptionViewPresentable! {
didSet {
viewModel.delegate = self
}
}
func configure(with viewModel: ReActivateSubscriptionViewPresentable) {
self.viewModel = viewModel
configureSubViews()
}
public static var isCollapsed = false
public class var collapsedActivateNowBtn: UIButton {
let activateButton = UIButton()
activateButton.frame = CGRect(x: 16.0, y: 112, width: UIScreen.main.bounds.width - 32, height: 33)
activateButton.applyStyle(Style.reActivateSubscriptionConfig.activateButton, text: Asset.String.reActivateButtonText, textAlignment: .center, shouldUnderline: true)
activateButton.addCornerRadius(radius: 6.0)
return activateButton
}
public func configureSubViews() {
self.backgroundColor = .black
self.reActiveSubscriptionLabel.applyStyle(Style.reActivateSubscriptionConfig.reActivateSubscribeLabel, text: Asset.String.reActivateText, textAlignment: .center)
self.activateNowButton.applyStyle(Style.reActivateSubscriptionConfig.activateButton, text: Asset.String.reActivateButtonText, textAlignment: .center, shouldUnderline: true)
self.addCornerRadius(radius: 6.0)
self.collapseSubscribeViewButton.setImage(Asset.Image.whiteUpArrow, for: .normal)
self.collapseSubscribeViewButton.addTarget(self, action: #selector(collapseActivateView), for: .touchUpInside)
self.activateNowButton.addTarget(self, action: #selector(activateSubscription), for: .touchUpInside)
ReActivateSubscriptionView.collapsedActivateNowBtn.addTarget(self, action: #selector(activateSubscription), for: .touchUpInside)
}
#objc func collapseActivateView() {
viewModel.handleCollapseTap()
}
#objc func activateSubscription() {
viewModel.activateSubscription()
}
}
I am trying to add the target action to my collapsedActivateNowBtn, but no action is performed on adding this target in configureSubViews
The configure(with viewModel: ReActivateSubscriptionViewPresentable) method is called after I instantiate the ReActivateSubscriptionView.
The question is a little unclear.
But here's how you correctly subclass UIButton so that it "knows" it has been clicked:
import UIKit
class MyButton: UIButton {
override func didMoveToSuperview() {
super.didMoveToSuperview()
addTarget(self, action: #selector(clicked), for: .touchUpInside)
}
#objc func clicked() {
print("I have been clicked")
}
}
(As a rule, always subclass. Don't try to add behaviors you need "from above" - subclass.)
Again it's unclear exactly what you're trying to do, OP, but this is how you make a button "know" what is happening.
Here I had placed two radio buttons on view controller class but unable to give logic to make a radio button active at a time can anyone help me ?
#IBAction func radioButtonAction(_ sender: KGRadioButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
workRadioButton.isSelected = false
} else{
}
}
#IBAction func WorkRadiobuttonAction(_ sender: KGRadioButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
homeRadioButton.isSelected = false
} else{
}
}
I am just using UIButton as radioButton.try like below
Create one array to store radio buttons
var radioButtonArray = [UIButton]()
Declare your radio buttons as UIButton or anyOther
#IBOutlet weak var radioButton1: UIButton!
#IBOutlet weak var radioButton2: UIButton!
Append all buttons into array
radioButtonArray.append(contentsOf: [radio1,radio2])
Set same target for all buttons
self.radioButton1.addTarget(self, action: #selector(self.folderRadioButtonClicked(_:)), for: UIControlEvents.touchUpInside)
self.radioButton2.addTarget(self, action: #selector(self.folderRadioButtonClicked(_:)), for: UIControlEvents.touchUpInside)
func folderRadioButtonClicked(_ sender:UIButton) {
for i in 0..<self.radioButtonArray.count {
if self.radioButtonArray[i] == sender{
// here you can perform what you want
self.radioButtonArray[i].setImage(UIImage(named: "checked.png"), for: UIControlState())
}else {
self.radioButtonArray[i].setImage(UIImage(named: "unchecked.png"), for: UIControlState())
}
}
}
I have two modified buttons to be a checkbox with a subclass, the checkbox is siCheckbox and noCheckbox. if siCheckbox is checked the other will be unchecked.
The problem is , if i press siCheckBox again will set noCheckbox checked and siCheckBox unchecked
this is my code
import UIKit
class Paso1: UIViewController, CheckBoxDelegate {
#IBOutlet weak var siCheckBox: CheckBox!
#IBOutlet weak var noCheckBox: CheckBox!
override func viewDidLoad() {
super.viewDidLoad()
self.siCheckBox.delegate = self
self.noCheckBox.delegate = self
}
func checkBoxDidChange(checkbox: CheckBox) {
if checkbox == self.siCheckBox {
self.noCheckBox.isChecked = !checkbox.isChecked
} else {
self.siCheckBox.isChecked = !checkbox.isChecked
}
}
and this is the subclass for the buttons checkbox
protocol CheckBoxDelegate {
func checkBoxDidChange(checkbox: CheckBox) -> Void
}
import UIKit
class CheckBox: UIButton {
// Images
let checkedImage = UIImage(named: "check-greenb")! as UIImage
let uncheckedImage = UIImage(named: "check-baseb")! as UIImage
var delegate: CheckBoxDelegate?
// Bool property
var isChecked: Bool = false {
didSet{
if isChecked == true {
self.setImage(checkedImage, forState: .Normal)
} else {
self.setImage(uncheckedImage, forState: .Normal)
}
}
}
override func awakeFromNib() {
self.addTarget(self, action: #selector(CheckBox.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
self.isChecked = false
}
func buttonClicked(sender: UIButton) {
isChecked = !isChecked
self.delegate?.checkBoxDidChange(self)
}}
is there any examples or a better way to do this?
If you don't want your button to change its checked property if it is already checked, just add conditional logic in your buttonClicked function.
func buttonClicked(sender: UIButton) {
if !isChecked {
isChecked = !isChecked
self.delegate?.checkBoxDidChange(self)
}
}
I think this is a bit complicate to do this.
What I would do :
#IBOutlet weak var siCheckBox: CheckBox!
#IBOutlet weak var noCheckBox: CheckBox!
override func viewDidLoad() {
super.viewDidLoad()
self.siCheckBox.setImage(checkedImage, forState: .Selected)
self.siCheckBox.setImage(uncheckedImage, forState: .Normal)
self.noCheckBox.setImage(checkedImage, forState: .Selected)
self.noCheckBox.setImage(uncheckedImage, forState: .Normal)
}
#IBAction func checkBoxAction(sender : UIButton) {
siCheckBox.isSelected = false
noCheckBox.isSelected = false
sender.isSelected = true
}
That way you don't even need to subclass your button and no delegate to set. Don't forget to link your two buttons to the checkbox action function ;)
I have the present code to allow selection of the days of the week for a repeating event. At present they are independent, and the duplication is high.
How can the buttons be refactored to reduce duplication?
// Array of days repeating:
var weekDayRepeat = [false,false,false,false,false,false,false]
var savedEventId : String = ""
#IBOutlet weak var datePickerStart: UIDatePicker!
#IBOutlet weak var datePickerEnd: UIDatePicker!
#IBOutlet weak var repeatSwitch: UISwitch!
#IBOutlet weak var monSelect: UIButton!
#IBOutlet weak var tuesSelect: UIButton!
#IBOutlet weak var wedsSelect: UIButton!
#IBOutlet weak var thursSelect: UIButton!
#IBOutlet weak var friSelect: UIButton!
#IBOutlet weak var satSelect: UIButton!
#IBOutlet weak var sunSelect: UIButton!
#IBOutlet weak var repeatingLabel: UILabel!
#IBAction func monSelect(sender: AnyObject) {
if(weekDayRepeat[0]) {
monSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[0] = false
} else {
monSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[0] = true
}
}
#IBAction func tuesSelect(sender: AnyObject) {
if(weekDayRepeat[1]) {
tuesSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[1] = false
} else {
tuesSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[1] = true
}
}
#IBAction func wedsSelect(sender: AnyObject) {
if(weekDayRepeat[2]) {
wedsSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[2] = false
} else {
wedsSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[2] = true
}
}
#IBAction func thursSelect(sender: AnyObject) {
if(weekDayRepeat[3]) {
thursSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[3] = false
} else {
thursSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[3] = true
}
}
#IBAction func friSelect(sender: AnyObject) {
if(weekDayRepeat[4]) {
friSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[4] = false
} else {
friSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[4] = true
}
}
#IBAction func satSelect(sender: AnyObject) {
if(weekDayRepeat[5]) {
satSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[5] = false
} else {
satSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[5] = true
}
}
#IBAction func sunSelect(sender: AnyObject) {
if(weekDayRepeat[6]) {
sunSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
weekDayRepeat[6] = false
} else {
sunSelect.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
weekDayRepeat[6] = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Set initial conditions of the page...:
repeatSwitch.on = true
datePickerStart.datePickerMode = UIDatePickerMode.Time
datePickerEnd.datePickerMode = UIDatePickerMode.Time
monSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
tuesSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
wedsSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
thursSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
friSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
satSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
sunSelect.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)
// Allow dynamically changing the mode given if repeating or not.
// If switch to repeating, then show selecting only the time and list of days to select/multi-select
repeatSwitch.addTarget(self, action: #selector(ViewController.switchChanged(_:)), forControlEvents: UIControlEvents.ValueChanged)
}
try the following code :
#IBOutlet var weekDayBtns: [UIButton]!
#IBAction func weekDayBtnAction(sender: UIButton) {
weekDayRepeat[sender.tag] = !weekDayRepeat[sender.tag]
sender.setTitleColor(weekDayRepeat[sender.tag] ? UIColor.blackColor():UIColor.lightGrayColor() , forState: UIControlState.Normal)
}
override func viewDidLoad() {
super.viewDidLoad()
weekDayBtns.forEach({$0.setTitleColor(UIColor.lightGrayColor(), forState: UIControlState.Normal)})
}
create an IBOutlet Collection: #IBOutlet var weekDayBtns: [UIButton]!
create an general IBAction :#IBAction func weekDayBtnAction(sender: UIButton){}
connect the btns all to IBOutlet Collection and IBAction
set the btn tag
here are screenshots:
#Sauron: One possible solution would be the following...
if each button is given a number as its title, you could replicate the technique used to make a simple calculator, where by...
the first button is used to create IBAction / func (kept as uibutton)
Subsequent buttons are then Control-dragged to the "ViewController" in the hierarchy in 'document outline' for the storyboard
When the popup shows. Go to the middle, under "sent events" which should have the name of the first button function you created
Do the same for all the other buttons
This helps to reduce duplication of the code writing. The buttons can then later be identified by their Title. E.g.
#IBAction func numberTapped(sender: UIButton) {
let nameOfDay = sender.currentTitle
}
Thus allowing you to utilise the weekday elsewhere within the code.
Found a youtube link that may help you quickly re: the duplication...?
https://www.youtube.com/watch?v=NJHsdjH2HdY