How to highlight the background of a UIButton when it is clicked and "unhighlight" it? - swift

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()

Related

How to implement checkbox in swift?

I am using this code for implementing checkbox but it is not working. Can anyone tell where I went wrong?
#IBAction func tapped(_ sender: UIButton){
if (checkBox.isSelected == false){
checkBox.setImage(UIImage(named: "circle_radio_selected"), for: .normal)
checkBox.isSelected = true;
} else {
checkBox.setImage(UIImage(named: "circle_radio_unselected"), for: .normal)
checkBox.isSelected = false;
}
The easy way of doing this is to already assign the images for different UIControl.State. I don't know if you have created this button using storyboard/xib or have created it programatically. I would do it like this:
private let checkbox: UIButton = {
let button = UIButton()
button.setImage(UIImage(named: "circle_radio_selected"), for: .selected)
button.setImage(UIImage(named: "circle_radio_unselected"), for: .normal)
return button
}()
Now, once your IBAction is called:
I am using this code for implementing checkbox but it is not working. Can anyone tell where I went wrong?
#IBAction func tapped(_ sender: UIButton){
checkBox.isSelected = sender.isSelected
// Now you have already set the images according to control state. Once it is selected it will change the image and when it is not selected it will become normal and select the other image
}
Also, it will be best if you can create a Constants file and add these named strings there.
You can set the images for normal/selected states in the interface builder, or you can do it programmatically, e.g.
override func viewDidLoad() {
super.viewDidLoad()
checkBox.setImage(UIImage(named: "circle_radio_unselected"), for: .normal)
checkBox.setImage(UIImage(named: "circle_radio_selected"), for: .selected)
}
Then your tap function can easily toggle the button state.
#IBAction func tapped(_ sender: UIButton) {
checkBox.isSelected.toggle()
}

How do I call an interstitial ad to load on another UIViewController?

I have a UIViewController with a UIView displayed on it; pressing a button on the UIView loads my interstitial ad. When the UIView is subsequently displayed, I want the interstitial to be displayed with the rootVC as the UIViewController.
However, this code does not seem to work as intended:
1) My View Controller:
class MyViewController: UIViewController {
let button: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("BUTTON", for: .normal)
btn.addTarget(self, action: #selector(showUIView), for: .touchUpInside)
return btn
}()
#objc func showUIView(_ sender: UIButton) {
let popUp = MyUIView()
self.view.addSubview(popUp)
}
2) My UIView:
class MyUIView: UIView {
var interstitial: GADInterstitial!
let button: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("UIVIEW BUTTON", for: .normal)
btn.addTarget(self, action: #selector(prepareInterstitial), for: .touchUpInside)
return btn
}()
#objc func prepareInterstitial(_ sender: UIButton) {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
let request = GADRequest()
interstitial.load(request)
dismissPopUp()
if interstitial.isReady {
interstitial.present(fromRootViewController: MyViewController())
}
}
I get this in the console:
Warning: Attempt to present <GADFullScreenAdViewController: 0x7f8611e22fc0> on <Project.MyViewController: 0x7f8612884800> whose view is not in the window hierarchy!`
which I do not understand because MyViewController is still very much a part of the view hierarchy.
I'd be really grateful if someone could show me how to fix this error, I'm relatively new to coding and not sure what I am doing wrong. Thank you!
The reason why this doesn't work is because you are creating a brand new VC here:
interstitial.present(fromRootViewController: MyViewController())
This MyViewController() is not the VC that is shown on the screen! You just created by calling its initialiser.
You need to somehow get the VC that's shown on the screen. One simple way to do this is to add a rootVC property to your MyUIView:
weak var rootVC: UIViewController?
And then present this instead:
if let rootVC = self.rootVC { // nil check!
interstitial.present(fromRootViewController: rootVC)
}
In showUIView, set self as rootVC:
#objc func showUIView(_ sender: UIButton) {
let popUp = MyUIView()
popUp.rootVC = self
self.view.addSubview(popUp)
}

Creating a checkbox programmatically using images as the UIButtons background

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
}
}

How to change UIButton's image every time it is pressed

How can I make a UIButton change image from A to B and again B to A, every time it's pressed?
Not as .normal to .highlighted, but permanent.
I've tried the .highlighted method because I can't find the code for permanent, here's my code:
func ChangeButton() {
Button.setImage(A, for: .normal)
Button.setImage(B, for: .highlighted)
Thanks for mentions of setBackgroundImage to Xavier L. from the other answer.
Try the following code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var button: UIButton!
var buttonActive = false
override func viewDidLoad() {
super.viewDidLoad()
button.setBackgroundImage(UIImage(named: "apple"), for: .normal)
}
#IBAction func buttonPressed() {
if buttonActive {
button.setBackgroundImage(UIImage(named: "apple"), for: .normal)
} else {
button.setBackgroundImage(UIImage(named: "pineapple"), for: .normal)
}
buttonActive = !buttonActive
}
}
And your storyboard should look like that:
N.B. On Stack Overflow you should perform some actions before asking. Try to include some code you tried.
I recommend changing the backgroundImage because it's scaled automatically, and the button text in front won't get covered.
If it's a custom button, within its initializer:
self.addTarget(self, action: #selector(*yourfunctoswitchimages*), for: .touchUpInside)
... and then that yourfunctoswitchimages can just check what the current background image is, and switch it accordingly.
If it's not a custom button, add a target to it in viewDidLoad or something. Here's a lot of sample code.
In your viewDidLoad()
yourButt.addTarget(self, action: #selector(switcheroo), for: .touchUpInside)
Another func in your view controller:
func switcheroo()
{
if yourButt.currentBackgroundImage == image1
{
yourButt.setBackgroundImage(image2), for: .normal)
}
else { // ...set image to image1 }
}
yourButt would be a property of your view controller of course, that way it's accessible to the viewDidLoad() and to other funcs within it.

Swift Reload textfield from button action

I have a button that creates many more buttons with a textfield:
func CreateButtonWithIndex(index:Int) {
let newButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
newButton.setTitle(“Button”, forState: UIControlState.Normal)
newButton.addTarget(self, action: Selector("go:"), forControlEvents: UIControlEvents.TouchUpInside)
newButton.tag = index+1;
var textFieldButton: UITextField = UITextField()
textFieldButton.tag = index+1;
textFieldButton.text = “textfield”
self.view.addSubview(textFieldButton)
self.view.addSubview(newButton)
}
func go(sender: AnyObject) {
println(“ok press button“)
}
How can I detect the textfield corresponding to the button pressed?
convert the sender into a UIButton
#IBAction func go(sender: AnyObject) {
let yourButton = sender as UIButton
println(yourButton.titleLabel.text)
}
Even better, if you're certain that only buttons are going to call the "go" action, you could instead do this:
#IBAction func go(sender: UIButton) {
println(sender.titleLabel.text)
if(sender.titleLabel.text == "OK")
println("OK button was pressed")
}
And more information can be found in the "Comparing Strings" section of Apple's Strings & Characters Swift documentation and the #IBOutlet thing I found in this tutorial.
Subclass UIButton. Add a UITextField variable to the subclassed UIButton. Assign the new UITextField variable after you create the UIButton subclass.
UIButton subclass:
class TextFieldButton: UIButton {
var textField: UITextField! // use this to reference the related text field
}
The code in your other class:
func CreateButtonWithIndex(index:Int) {
let newButton = UIButton.buttonWithType(UIButtonType.System) as TextFieldButton // use our new subclass
newButton.setTitle(“Button”, forState: UIControlState.Normal)
newButton.addTarget(self, action: Selector("go:"), forControlEvents: UIControlEvents.TouchUpInside)
newButton.tag = index+1;
var textFieldButton: UITextField = UITextField()
textFieldButton.tag = index+1;
textFieldButton.text = "textfield"
newButton.textField = textFieldButton // set reference to the text field
self.view.addSubview(textFieldButton)
self.view.addSubview(newButton)
}
func go(sender: AnyObject) {
println("ok press button")
println(sender.textField) // now we can access the related text field
}