I have a floating button in my app that display 5 different buttons. Each of them has a color but initially are gray. When the user selects one of the buttons, all of them hide, and when the user taps again on the floating button, the button that was previously tapped is not gray but with its proper color.
Also the logic would be that the user can tap another one of the buttons to select it, and the previous one would be unselected, as if the user taps on a selected button, it gets unselected.
I'm using cocoa pods for the Floating Button, JJFloatingActionButton, but on the documentation there is no info about this.
func configureActionButton() {
actionButton.overlayView.backgroundColor = UIColor(white: 0, alpha: 0.5)
actionButton.buttonImage = UIImage(systemName: "line.horizontal.3.decrease")
actionButton.buttonColor = UIColor(named: "signoColor")!
actionButton.buttonImageColor = .white
actionButton.buttonImageSize = CGSize(width: 30, height: 30)
actionButton.itemAnimationConfiguration = .slideIn(withInterItemSpacing: 14)
actionButton.itemSizeRatio = CGFloat(0.75)
let item = actionButton.addItem()
item.titleLabel.text = "Button 1"
item.buttonColor = UIColor(red: 254/255.0, green: 224/255.0, blue: 255/255.0, alpha: 1.0)
item.buttonImageColor = UIColor(red: 200/255.0, green: 73/255.0, blue: 203/255.0, alpha: 1.0)
item.imageSize = CGSize(width: 30, height: 30)
item.action = { item in
//This is for the functionality of the button
}
let item2 = actionButton.addItem()
item2.titleLabel.text = "Button 2"
item2.buttonColor = UIColor(red: 254/255.0, green: 224/255.0, blue: 255/255.0, alpha: 1.0)
item2.buttonImageColor = UIColor(red: 200/255.0, green: 73/255.0, blue: 203/255.0, alpha: 1.0)
item2.imageSize = CGSize(width: 30, height: 30)
item2.action = { item in
//This is for the functionality of the button
}
//And I have 3 more buttons
}
This is how the floating button looks like:
I would appreciate some help. I've searched for similar questions but none of them solved this problem. Thank you!
Related
Button Method
#objc func buttonFuction(){
let stacView = UIStackView()
stacView.spacing = 12
stacView.distribution = .fillEqually
stacView.axis = .horizontal
stacView.translatesAutoresizingMaskIntoConstraints = false
view!.addSubview(stacView)
buttonNames = ["One","Two","Three","Four"]
for i in 0..<buttonNames.count{
index+=i
button = Button()
button.setTitle(buttonNames[i], for: .normal)
stacView.addArrangedSubview(button)
buttons.append(button)
button.tag = index
button.addTarget(self, action: selectors[i], for: .touchUpInside)
button.addTarget(self, action: selectorsColor[i], for: .touchDown)
}
NSLayoutConstraint.activate([stacView.centerXAnchor.constraint(equalTo: view!.centerXAnchor),stacView.centerYAnchor.constraint(equalTo: view!.centerYAnchor),stacView.widthAnchor.constraint(equalToConstant: 350),stacView.heightAnchor.constraint(equalToConstant:70)])
}
Button handler methods
#objc func colorButton1(){
if button.tag == 0 {
button.backgroundColor = #colorLiteral(red: 0.1123025946, green: 1, blue: 0.03079073749, alpha: 1)
}
else {
button.backgroundColor = #colorLiteral(red: 0.7974829231, green: 0.09321228972, blue: 0.09321228972, alpha: 1)
}
}
#objc func colorButton2(){
if button.tag == 1 {
button.backgroundColor = #colorLiteral(red: 0.07117979832, green: 0.8973241221, blue: 0, alpha: 1)
}
else {
button.backgroundColor = #colorLiteral(red: 0.7312681945, green: 0.1133923198, blue: 0.06002510149, alpha: 1)
}
}
#objc func colorButton3(){
if button.tag == 2 {
button.backgroundColor = #colorLiteral(red: 0.1123025946, green: 1, blue: 0.03079073749, alpha: 1)
}
else {
button.backgroundColor = #colorLiteral(red: 0.6805654408, green: 0.1003367522, blue: 0.09689761347, alpha: 1)
}
}
#objc func colorButton4(){
if button.tag == 3 {
button.backgroundColor = #colorLiteral(red: 0.1123025946, green: 1, blue: 0.03079073749, alpha: 1)
}
else {
button.backgroundColor = #colorLiteral(red: 0.7620294414, green: 0.05229266211, blue: 0.09308676813, alpha: 1)
}
}
Every time I press the button it keeps changing colour to the last button, even after tagging each button, the colour change only occurs in the last button and not sure how to change the code to allow the colour change to happen on other button when pressed.
Thank you in advance.
As I said in the comments, the buttons array contains 4 items which all point – due to reference semantics – to the same instance, the lastly added Button instance. So does also the button property.
You need something like this, it creates four different Button instances and uses one action method, I don't know what the second selector does so I commented it out.
The logic: The sender parameter is the just tapped button, first set all background colors except the current button to their appropriate red colors, then set the background color of the current button to the green color. The references to the buttons are taken from the buttons array.
for i in 0..<buttonNames.count{
let button = Button()
button.setTitle(buttonNames[i], for: .normal)
stacView.addArrangedSubview(button)
buttons.append(button)
button.tag = i
button.addTarget(self, action: #selector(colorButton), for: .touchUpInside)
// button.addTarget(self, action: selectorsColor[i], for: .touchDown)
}
#objc func colorButton(_ sender : Button) {
let offColors = [#colorLiteral(red: 0.7974829231, green: 0.09321228972, blue: 0.09321228972, alpha: 1),
#colorLiteral(red: 0.7312681945, green: 0.1133923198, blue: 0.06002510149, alpha: 1),
#colorLiteral(red: 0.6805654408, green: 0.1003367522, blue: 0.09689761347, alpha: 1),
#colorLiteral(red: 0.7620294414, green: 0.05229266211, blue: 0.09308676813, alpha: 1)]
for i in 0..<4 where i != sender.tag {
buttons[i].backgroundColor = offColors[i]
}
switch sender.tag {
case 0: sender.backgroundColor = #colorLiteral(red: 0.1123025946, green: 1, blue: 0.03079073749, alpha: 1)
case 1: sender.backgroundColor = #colorLiteral(red: 0.07117979832, green: 0.8973241221, blue: 0, alpha: 1)
case 2: sender.backgroundColor = #colorLiteral(red: 0.1123025946, green: 1, blue: 0.03079073749, alpha: 1)
case 3: sender.backgroundColor = #colorLiteral(red: 0.1123025946, green: 1, blue: 0.03079073749, alpha: 1)
default: break
}
}
So I've got these buttons (3 stacks of 6, so 18), and what I want to achieve is when I press one of these buttons :
border color & text color changes
the other buttons are reset to their normal styling
But I don't want to disable the others via a "isEnabled" trick (I've only found solutions here involving isEnabled), I still want them to be enabled, I just want them not to be "highlighted" with my custom styling when one is pressed.
for the first part which is just the styling I did this inside the IBAction :
#IBAction func preset1Pressed(_ sender: UIButton) {
preset1.layer.borderColor = #colorLiteral(red: 0.4095217415, green: 0.6107917746, blue: 0.2774988226, alpha: 1)
preset1.layer.borderWidth = 0.42
preset1.setTitleColor(#colorLiteral(red: 0.4095217415, green: 0.6107917746, blue: 0.2774988226, alpha: 1), for: .normal)
}
This small portion was just for 1 button, but I guess if I have 18 of them I should make a class or a struct rather than copy this inside each IBAction ?? Or a func ?
Then for the 2nd part I'm not sure about how to do it, reversing to the original properties (set in the Attributes Inspector) of the other buttons when one is pressed.
Intuitively I'm sure it's a combination of an array of all the 18 buttons inside a function that would loop through all the array, and maybe make a bool on each button to check if they are pressed or not, but I really don't know how the syntax would be...
Worth noting also that if I press twice on the same button I don't want it to reverse to its original properties but to keep the "pressed" styling.
Thanks in advance !
Define UIButton array and add buttons when you add it to stack.set index as button tag (0-17)
fileprivate var btnArray:[UIButton] = []
btn0.tag = 0
btnArray.appent(btn0)
Then you can change style in button click function like this
#IBAction func preset1Pressed(_ sender: UIButton) {
btnArray.forEach { (button) in
if button.tag == sender.tag {
preset1.layer.borderColor = #colorLiteral(red: 0.4095217415, green: 0.6107917746, blue: 0.2774988226, alpha: 1)
preset1.layer.borderWidth = 0.42
preset1.setTitleColor(#colorLiteral(red: 0.4095217415, green: 0.6107917746, blue: 0.2774988226, alpha: 1), for: .normal)
view.layoutIfNeeded()
}else{
//add default style
view.layoutIfNeeded()
}
}
}
Don't frogot to add view.layoutIfNeeded() after this
So what suggested Dilan did not completely solve it on its own, though I experimented with it and it actually helped me solve it, apart I did these modifications :
I created my Array of buttons (called presetsArray) and tagged them.
Then I created a function to be called in all IBActions, but as sender.tag wouldn't work here's how I worked out the function :
func styleButtons(tag: Int) {
let tag = tag
presetsArray.forEach{ (button) in
if button.tag == tag {
button.layer.borderColor = #colorLiteral(red: 0.4095217415, green: 0.6107917746, blue: 0.2774988226, alpha: 1)
button.layer.borderWidth = 0.42
button.setTitleColor(#colorLiteral(red: 0.4095217415, green: 0.6107917746, blue: 0.2774988226, alpha: 1), for: .normal)
view.layoutIfNeeded()
} else {
button.layer.borderColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
button.setTitleColor(#colorLiteral(red: 0.4978774786, green: 0.5020093918, blue: 0.5019439459, alpha: 1), for: .normal)
}
}
}
Then in each IBAction for preset X I would call it like this :
styleButtons(tag: presetX.tag)
In the else section of my function as view.layoutIfNeeded() wouldn't reverse back to my original styling I just went for the color picker and picked my original styling, not the most legit way to do this I feel but it works !
Thanks a lot Dilan for the help.
I'm trying to show a subview that has been added to a view, but it does not show up when the button is pressed.
I have tried setting isOpaque to 1, alpha to 1, isHidden to false (without needing to press the button) and have checked that I have run view.addSubview(). I have also found out that the subview is not hidden at all but the background is white (it is supposed to be blue or red).
code to add subviews
//setup
viewBGKRect = CGRect(x: 20, y: 20, width: 984, height: 660)
viewBGK = UIView(frame: viewBGKRect)
viewBGK.backgroundColor = UIColor(red: 139.0, green: 206.0, blue: 231.0, alpha: 1.0)
viewBGK.alpha = 1
viewBGK.isOpaque = true
viewRGKRect = CGRect(x: 20, y: 20, width: 984, height: 660)
viewRGK = UIView(frame: viewRGKRect)
viewRGK.backgroundColor = UIColor(red: 240.0, green: 177.0, blue: 187.0, alpha: 1.0)
viewRGK.alpha = 1
viewRGK.isOpaque = true
//isHidden is set to false when the buttons are pressed
viewBGK.isHidden = true
viewRGK.isHidden = true
view.addSubview(viewBGK)
view.addSubview(viewRGK)
code to show subviews
#IBAction func goalkeeper(_ sender: UIButton) {
switch sender.tag {
case 0:
// blue
viewBGK.isHidden = false
viewRGK.isHidden = true
return
default:
viewBGK.isHidden = true
viewRGK.isHidden = false
return
}
}
I expect a blue/red rectangle to appear at the top of the screen but it does not show.
Nevermind I found the answer:
UIColor RGB is from 0-1 not 0-255 the colors should be
(blue)
UIColor(red:0.55, green:0.81, blue:0.91, alpha:1.0)
and
(red)
UIColor(red:0.94, green:0.69, blue:0.73, alpha:1.0)
not
(blue)
UIColor(red: 139.0, green: 206.0, blue: 231.0, alpha: 1.0)
and
(red)
UIColor(red: 240.0, green: 177.0, blue: 187.0, alpha: 1.0)
i feel really dumb now.
If you're going to utilize custom colors, it might be easier to declare them somewhere other than in a view controller. One approach would be to declare them in an extension. To do this, you would do the following:
Create a new Swift file and name it UIColor+Extension.swift
Inside the new file, add the following code:
extension UIColor {
static var customBlue: UIColor {
return #colorLiteral(red: 0.5450980392, green: 0.8078431373, blue: 0.9058823529, alpha: 1)
}
static var customRed: UIColor {
return #colorLiteral(red: 0.9411764706, green: 0.6941176471, blue: 0.7333333333, alpha: 1)
}
}
I didn't type those colors out. I simply typed return Color Literal and it showed a white rounded rectangle. When I clicked on the rectangle, I saw this:
Then, I clicked the "Other" button and I typed in the RGB values:
Lastly, you want to avoid writing repetitive code (DRY = don't repeat yourself). Here's the updated code:
//setup
viewBGKRect = CGRect(x: 20, y: 20, width: 984, height: 660)
viewBGK = UIView(frame: viewBGKRect)
viewBGK.backgroundColor = .customBlue
viewRGKRect = CGRect(x: 20, y: 20, width: 984, height: 660)
viewRGK = UIView(frame: viewRGKRect)
viewRGK.backgroundColor = .customRed
[viewBGK, viewRGK].forEach { view in
view.alpha = 1
view.isOpaque = true
//isHidden is set to false when the buttons are pressed
view.isHidden = true
}
I have an alert controller that I set to a new tint color with this line of code:
alertController.view.tintColor = UIColor(red: 0.59, green: 0.59, blue: 0.59, alpha: 1.0)
The color does show correctly, but once the alert action is tapped, it changes back to the default blue color automatically. How can I make it so that the tint color does not change back to default. I have heard of the func tintColorDidChange() but I am unsure of how to use it?
You can try this. It has been discussed here
you should add the same code in presentViewController completion handler
presentViewController(alert, animated: true) {
alert.view.tintColor = UIColor(red: 0.59, green: 0.59, blue: 0.59, alpha: 1.0)
}
I'm new to coding and have been attempting to put myself through an intensive course in swift. Right now I'm working on a project that I would like to have a IBAction button that completes "set 1" of instructions on first press, then "set 2" of instructions on second press. Then, press 3 would revert back to "set 1" instructions, press 4 "set 2" and so forth.
Forgive me if this is elementary, but any help would be appreciated.
//Set 1 instructions with the IBAction would be
#IBAction func punchInButtonPressed(sender: AnyObject) {
statusLabel.text = "Status: Punched In"
statusLabel.backgroundColor = UIColor(red: 96/255.0, green: 191/255.0, blue: 111/255.0, alpha: 1.0)
//Set 2 instructions would be
statusLabel.text = "Status: Punched Out"
statusLabel.backgroundColor = UIColor(red: 255/255.0, green: 110/255.0, blue: 115/255.0, alpha: 1.0)
You can handle this by adding a variable to your class that will hold the "state" of the button - punched in or punched out. Then, when the button is pressed, you toggle the state and then display the correct message:
class MyViewController: UIViewController {
var punchedIn = false
// rest of declarations
#IBAction func punchInButtonPressed(sender: AnyObject) {
// toggle status
punchedIn = !punchedIn
// show correct message
if punchedIn {
// set 1
statusLabel.text = "Status: Punched In"
statusLabel.backgroundColor = UIColor(red: 96/255.0, green: 191/255.0, blue: 111/255.0, alpha: 1.0)
} else {
// set 2
statusLabel.text = "Status: Punched Out"
statusLabel.backgroundColor = UIColor(red: 255/255.0, green: 110/255.0, blue: 115/255.0, alpha: 1.0)
}
}
}