In my app I'm using UIButton as check button. I have around 10 UIButton which all should toggle between two Image. An image which shows a "x" and another which shows a check mark. I have an action event for each UIButton, but since all 10 UIButton toggle between two images, is there a way to achieve this the best way. Right now I only know this solution, where I have a Boolean flag for each button and when toggle I set the flag to either true or false. But for me this seems like a bad practice.
Example for one of the UIButton:
var MenuBtnSelect = false
func GlutenSelect(sender: AnyObject)
{
if(!MenuBtnSelect)
{
sender.setImage(UIImage(named: "CheckMark"), forState: .Normal)
MenuBtnSelect = true
}
else
{
sender.setImage(UIImage(named: "NotCheckMark"), forState: .Normal)
MenuBtnSelect = false
}
}
First of all you have to set the NotCheckMark image for every button, then you can create the same without the boolean flag.
#IBAction func pushAnyButton(sender: AnyObject) {
if let btnImage : UIButton = sender as? UIButton {
if (btnImage.currentImage == UIImage(named: "CheckMark"))
{
btnImage.setImage(UIImage(named: "NotCheckMark"), forState: .Normal)
}
else
{
btnImage.setImage(UIImage(named: "CheckMark"), forState: .Normal)
}
}
}
You can use this function for all the 10 button if you connect this method to the buttons. Or you can this in more compact way like this:
#IBOutlet weak var anyCheckBoxButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
anyCheckBoxButton.setImage(UIImage(named: "CheckMark"), forState: .Selected )
anyCheckBoxButton.setImage(UIImage(named: "NotCheckMark"), forState: .Normal )
}
#IBAction func pushAnyCheckBoxButton(sender: AnyObject) {
anyCheckBoxButton.selected = !anyCheckBoxButton.selected
}
The second idea came from here.
Just give every button you want to use as a check mark a tag = 1000. if sender.tag == 1000 it is off, set it to 1001 and change the image. Try like this:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func switchImage(sender: UIButton) {
sender.toggleSwitch
}
}
extension UIButton {
var toggleSwitch: Bool {
if tag == 1000 {
tag = 1001
setImage(UIImage(named: "CheckMark"), forState: .Normal)
return true
} else {
tag = 1000
setImage(UIImage(named: "NotCheckMark"), forState: .Normal)
return false
}
}
}
Related
Need to save ther value from the radio button to a variable
#IBOutlet weak var userButton: UIButton!
#IBOutlet weak var propertyButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func btClicked (sender: UIButton) {
let buttonArray = [userButton , propertyButton]
buttonArray.forEach {_ in
$0?.isSelected = false
}
}
create a variable to store the value of button
var strVal = ""
create two different outlet for both button
#IBAction func btnUserClicked(_ sender: UIButton) {
setValue(isUser: true)
}
#IBAction func btnPropertyOwnerClicked(_ sender: UIButton) {
setValue(isUser: false)
}
the setValue(isUser : Bool) method will store your selected button value and change image of button according to selection
func setValue(isUser : Bool){
if isUser{
strVal = "User"
btnUser.setImage(UIImage(named: "circle-fill"), for: .normal)
btnPropertyOwner.setImage(UIImage(named: "circle"), for: .normal)
}
else{
strVal = "Property Owner"
btnPropertyOwner.setImage(UIImage(named: "circle-fill"), for: .normal)
btnUser.setImage(UIImage(named: "circle"), for: .normal)
}
}
the image 'circle' is your default image that is already on button and the image 'circle-fill' is to indicate whether or not your button is selected.
or you can use sender.tag property of button :
#IBAction func btnUserClicked(_ sender: UIButton) {
//setValue(isUser: true)
if(sender.tag == 0){
strVal = "user"
btnUser.setImage(UIImage(named: "circle-fill"), for: .normal)
btnPropertyOwner.setImage(UIImage(named: "circle"), for: .normal)
}
else{
strVal = "property user"
btnPropertyOwner.setImage(UIImage(named: "circle-fill"), for: .normal)
btnUser.setImage(UIImage(named: "circle"), for: .normal)
}
}
In my ViewController,
there is multiple buttons connected to the same action
my button is like check or uncheck
I have tried below
My action is triggered, but image didn't change
var uncheckBoxImage = UIImage(named: "uncheckBox")
var checkBoxImage = UIImage(named: "checkBox")
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons{
button?.setImage(uncheckBoxImage, for: .normal)
//every button I set uncheckBoxImage first.
}
}
#IBAction func btnAction(_ sender: UIButton) { //connect every button
if sender.imageView == checkBoxImage {
sender.setImage(uncheckBoxImage, for: .normal)
}else {
sender.setImage(checkBoxImage, for: .normal)
}
}
I also tried below, but it can't process multiple button
var cube:Bool = false
#IBAction func btnAction(_ sender: Any) {
cube = !cube
if cube {
sender.setImage(checkBoxImage, for: .normal)
} else {
sender.setImage(uncheckBoxImage, for: .normal)
}
}
How should I fix these situation ?
Like it has some questions for you
And you just need to click to be check or click again to be uncheck
The trick is to use the selectedState for buttons.
Set both images for .normal and .selected state:
button?.setImage(uncheckBoxImage, for: .normal)
button?.setImage(checkBoxImage, for: .selected)
then, in IBAction:
#IBAction func btnAction(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
...
}
You should implement different button's state, it will change image automatically
var uncheckBoxImage = UIImage(named: "uncheckBox")
var checkBoxImage = UIImage(named: "checkBox")
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons{
button?.setImage(uncheckBoxImage, for: .normal)
button?.setImage(checkBoxImage, for: .selected)
}
}
#IBAction func btnAction(_ sender: UIButton) { //connect every button
sender.isSelected = !sender.isSelected
}
Hi Please try with a tintcolor if that works
var uncheckBoxImage = UIImage(named: "uncheckBox")
var checkBoxImage = UIImage(named: "checkBox")
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons{
button?.setImage(uncheckBoxImage, for: .normal)
button?.tintColor = UIColor.clear
}
}
#IBAction func btnAction(_ sender: UIButton) {
if sender.tintColor == UIColor.clear {
sender.setImage(checkBoxImage, for: .normal)
sender.tintColor = UIColor.green
}else if sender.tintColor == UIColor.green {
sender.setImage(uncheckBoxImage, for: .normal)
sender.tintColor = UIColor.clear
}
}
For just two states, abstracting "normal" and "selected", it's better to use the above answers, but if you need to handle multiple cases, you can use <#UIButton#>.currentImage!.isEqual(to: foo), to compare images and use only .normal state.
This is an example:
#IBAction func btnAction(_ sender: UIButton) {
if sender.currentImage != nil && sender.currentImage!.isEqual(UIImage(named: "a")) {
sender.setImage(UIImage(named: "b"), for: .normal)
} else {
sender.setImage(UIImage(named: "a"), for: .normal)
}
}
If you want multiple selection then you can use.
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons {
button.setImage(UIImage(named: "uncheckBox"), for: .normal)
button.setImage(UIImage(named: "checkBox"), for: .selected)
button.tintColor = .clear
}
}
#IBAction func btnAction(_ sender: UIButton) {
// toggle automatic changes selection state
sender.isSelected.toggle()
}
I have seen multiple questions on how to implement a checkbox by just changing the background image when clicked, but I don't understand why the checkbox only shows when I add it to my ViewController setupViews.
It simply will not show up or change when I have all the functionality in my actionButton function. Should i be using a protocol and delegate set up to get my button showing changing when clicked? Below is my code, I am hoping someone can shed some light as to what I am missing here?
class MainMenuViewController: UIViewController {
let clickingCheckbox = ClickingCheckbox()
var checkbox = UIImage(named: "Checked_Checkbox")
var empty_checkbox = UIImage(named:"Empty_Checkbox")
var isBoxClicked: Bool!
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
self.backgroundImage.addSubview(contentView)
self.contentView.addSubview(clickingCheckbox)
clickingCheckbox.snp.makeConstraints { (make) in
make.top.equalTo(signInButton.snp.bottom).offset(-MainMenuViewController.padding)
make.leading.equalTo(buttonView)
make.width.equalTo(signInButton).multipliedBy(0.2)
make.height.equalTo(clickingCheckbox.snp.width)
}
clickingCheckbox.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
clickingCheckbox.setImage(empty_checkbox, for: UIControlState.normal) #The checkbox only shows on screen if I put it here, however it does nothing when clicked!
}
#objc func buttonAction(_ sender: ClickingCheckbox) {
if isBoxClicked == true {
isBoxClicked = false
}else{
isBoxClicked = true
}
if isBoxClicked == true {
sender.setImage(checkbox, for: UIControlState.selected)
}else{
sender.setImage(empty_checkbox, for: UIControlState.normal)
}
print("test")
}
In my Class I have.....
class ClickingCheckbox: UIButton {
override func draw(_ rect: CGRect) {
super.draw(rect)
}
}
I have tried keeping the buttonAction functionality in the class, but that didn't work, I have tried a multiple different ways but can't get my head around how to show it working. All other advice is given to implement using IBOutlets so this would be really helpful for me to understand. Thanks
Try something like this:
class ClickingCheckbox: UIButton {
convenience init() {
self.init(frame: .zero)
self.setImage(UIImage(named: "Empty_Checkbox"), for: .normal)
self.setImage(UIImage(named: "Checked_Checkbox"), for: .selected)
self.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}
#objc private func buttonTapped() {
self.isSelected = !self.isSelected
}
}
So basically this what I tried:
#IBAction func buttonTwo(sender: UIButton){ // <- Should UIButton be AnyObject ?
buttonOne.setTitle("Do", forState: .Normal) // This wont change the other buttons text
}
// After knowing how to this, my goal is to follow this logic:
#IBAction func buttonTwo(sender: UIButton) {
if ( buttonOne == "What") {
buttonOne.setTitle("Do", forState: .Normal)
} else {
buttonOne.setTitle(¨What", forState: .Normal)
}
}
I think this is what you are looking for:
#IBAction func buttonTwo(sender: UIButton) {
if let text = buttonOne.titleForState(UIControlState.Normal) { //make sure title is not nil
if ( text == "What") {
buttonOne.setTitle("Do", forState: .Normal)
} else {
buttonOne.setTitle("What", forState: .Normal)
}
}
}
I just ran this fine:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var buttonOne: UIButton!
#IBAction func changeText(sender: AnyObject) {
if let text = buttonOne.titleForState(UIControlState.Normal) {
if ( text == "What") {
buttonOne.setTitle("Do", forState: .Normal)
} else {
buttonOne.setTitle("What", forState: .Normal)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
are you sure the #IBOutlet is connected properly for buttonOne?
NOTE: when creating the #IBAction from the story board it sets sender to AnyObject. I changed it to see if it worked as UIButton and it does.
an array option like you asked
class ViewController: UIViewController {
#IBOutlet weak var buttonOne: UIButton!
var buttonArray:[UIButton] = []
#IBAction func changeText(sender: UIButton) {
if let text = buttonArray[0].titleForState(UIControlState.Normal) {
if ( text == "What") {
buttonArray[0].setTitle("Do", forState: .Normal)
} else {
buttonArray[0].setTitle("What", forState: .Normal)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
buttonArray.append(buttonOne)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I am trying to create 4 UIButtons that highlight and stay highlighted when they are clicked. The only problem is I need only one UIButton to be Highlighted at a time. So, if there is a UIButton highlighted already, I need it to be "unhighlighted" and highlight the UIButton I clicked. I have tried to do this before and failed. Please help me with this problem.
I am using the Swift coding language to do this.
Any input or suggestions would be greatly appreciated.
If you give this answer an upvote, remember to upvote dasblikenlight's answer as well.
class ViewController: UIViewController {
// Connect all 4 buttons to this outlet
#IBOutlet var radioGroup: [UIButton]!
// Connect this action to all 4 buttons
#IBAction func radioGroupClicked(sender: AnyObject) {
// Unhighlight all buttons
unhighlightRadioGroup()
// Highlight the one being clicked on
highlightRadioGroup(sender as! UIButton)
}
// Set all 4 buttons in unselected state
func unhighlightRadioGroup() {
for button in radioGroup {
button.selected = false
}
}
// Set one button in the selected state
func highlightRadioGroup(button : UIButton) {
button.selected = true
}
}
You can do it with an IBOutletCollection. Command-drag one of the buttons into the view controller code, and choose creating of an IBOutletCollection on drop, and name your collection something - say, radioGroup. Then control-drag the remaining three buttons into the same IBOutletCollection.
Next thing is to add a method to un-highlight all buttons in your radioGroup. This can be done with a simple loop.
Finally, add calls to unhighlightRadioGroup from the event handler of your buttons. Event handler should first call your unhighlightRadioGroup method, and then highlight the sender received in the event handler.
lazy var buttonsArray: [UIButton] = {
var buttons = [UIButton]()
let firstButton = UIButton()
let secondButton = UIButton()
let thirdButton = UIButton()
let fourthButton = UIButton()
buttons = [firstButton, secondButton, thirdButton, fourthButton]
return buttons
}()
private func setupButtonMethods() {
filteredButtons[0].addTarget(self, action: #selector(firstButtonPressed(sender:)), for: .touchUpInside)
filteredButtons[1].addTarget(self, action: #selector(secondButtonPressed(sender:)), for: .touchUpInside)
filteredButtons[2].addTarget(self, action: #selector(thirdButtonPressed(sender:)), for: .touchUpInside)
filteredButtons[3].addTarget(self, action: #selector(fourthButtonPressed(sender:)), for: .touchUpInside)
}
private func setupHiglightedStateOnButton(button: UIButton) {
for btn in buttonsArray {
btn.isSelected = false
btn.backgroundColor = .gray
btn.setTitleColor(.white, for: .normal)
btn.isUserInteractionEnabled = true
}
button.isSelected = true
button.backgroundColor = .yellow
button.setTitleColor(.black, for: .normal)
button.isUserInteractionEnabled = false
}
#objc func firstButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
#objc func secondButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
#objc func thirdButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
#objc func fourthButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
remember to call setupButtonMethods() inside viewDidLoad()