The tag system for the question isn't working as the exchange change only occurs on the last button - swift

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

Related

Swift How to process multiple button UI elegantly?

In my viewController I need to process button UI
I think my approach to process UI is not efficient
What if someday I need to do more button?
Today I just happen to have only three.....
Just want user press one of three, and others keep original color
like make user feel which one they press in many button
Here's my #IBAction
#IBAction func btnPress (_ sender: UIButton) {
let clickedBackgroundColor = UIColor(red: 1, green: 153, blue: 202, a: 1)
let clickedTextColor = UIColor(red: 255, green: 255, blue: 255, a: 1)
let originBackgroundColor = UIColor(red: 216, green: 247, blue: 250, a: 1)
let originTextColor = UIColor(red: 0, green: 71, blue: 88, a: 1)
switch sender {
case btnA:
btnA.backgroundColor = clickedBackgroundColor
btnA.setTitleColor(clickedTextColor, for: .normal)
btnA.underline()
btnB.backgroundColor = originBackgroundColor
btnB.setTitleColor(originTextColor, for: .normal)
btnC.backgroundColor = originBackgroundColor
btnC.setTitleColor(originTextColor, for: .normal)
case btnB:
btnB.backgroundColor = clickedBackgroundColor
btnB.setTitleColor(clickedTextColor, for: .normal)
btnB.underline()
btnA.backgroundColor = originBackgroundColor
btnA.setTitleColor(originTextColor, for: .normal)
btnC.backgroundColor = originBackgroundColor
btnC.setTitleColor(originTextColor, for: .normal)
case btnC:
btnC.backgroundColor = clickedBackgroundColor
btnC.setTitleColor(clickedTextColor, for: .normal)
btnC.underline()
btnA.backgroundColor = originBackgroundColor
btnA.setTitleColor(originTextColor, for: .normal)
btnB.backgroundColor = originBackgroundColor
btnB.setTitleColor(originTextColor, for: .normal)
default:break
}
}
And My UIButton Extension for adding underline
I can only add underline but how to remove it if user click other button?
extension UIButton {
func underline() {
guard let text = self.titleLabel?.text else { return }
let attributedString = NSMutableAttributedString(string: text)
attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSRange(location: 0, length: text.count))
self.setAttributedTitle(attributedString, for: .normal)
}
}
I'm really new, not good at questioning if need more info just ask for me, Thanks.
You simply can create an Outlet Collection for all buttons instead of explicitly creating an array of buttons and use that to set the button's properties as per the selection, i.e.
#IBOutlet var buttons: [UIButton]!
Usage:
#IBAction func btnPress (_ sender: UIButton) {
let clickedBackgroundColor = UIColor(red: 1, green: 153, blue: 202, a: 1)
let clickedTextColor = UIColor(red: 255, green: 255, blue: 255, a: 1)
let originBackgroundColor = UIColor(red: 216, green: 247, blue: 250, a: 1)
let originTextColor = UIColor(red: 0, green: 71, blue: 88, a: 1)
buttons.forEach { (button) in
button.backgroundColor = (button == sender) ? clickedBackgroundColor : originBackgroundColor
button.setTitleColor((button == sender) ? clickedTextColor : originTextColor, for: .normal)
if button == sender {
button.underline()
}
}
}
Note: Also, there is no need to traverse the array twice. One single traversal will work fine.

How to customize outlined button using MDCButtons in Swift?

I'm customizing my UIButton using MDCButton. I want to make my button outlined and customize its color.
In this case, I'm using MDCOutlinedButtonThemer.
I also implement MDCButton (MDCButtonColorThemer) with custom color in other button and it working.
I've tried to set my button with default MDCOutlinedButton and it works.
This is my code :
MDCOutlinedButtonThemer.applyScheme(buttonScheme, to: self.btnAddToCart)
MDCButtonColorThemer.applySemanticColorScheme(ApplicationScheme.shared.colorScheme, to: self.btnBuy)
This is the ApplicationScheme.swift :
public let colorScheme: MDCColorScheming = {
let scheme = MDCSemanticColorScheme(defaults: .material201804)
//TODO: Customize our app Colors after this line
scheme.primaryColor = UIColor(red: 255.0 / 255.0, green: 201.0 / 255.0, blue: 46.0 / 255.0, alpha: 1)
//scheme.primaryColorVariant = UIColor(red: 68.0/255.0, green: 44.0/255.0, blue: 46.0/255.0, alpha: 1.0)
//scheme.onPrimaryColor = UIColor(red: 255.0/255.0, green: 201.0/255.0, blue: 46.0/255.0, alpha: 1.0)
scheme.secondaryColor = UIColor(red: 254.0/255.0, green: 201.0/255.0, blue: 46.0/255.0, alpha: 1.0)
//scheme.onSecondaryColor = UIColor(red: 68.0/255.0, green: 44.0/255.0, blue: 46.0/255.0, alpha: 1.0)
scheme.surfaceColor = UIColor(red: 255.0/255.0, green: 201.0/255.0, blue: 46.0/255.0, alpha: 1.0)
//scheme.onSurfaceColor = UIColor(red: 255.0/255.0, green: 201.0/255.0, blue: 46.0/255.0, alpha: 1.0)
scheme.backgroundColor = UIColor(red: 255.0/255.0, green: 201.0/255.0, blue: 46.0/255.0, alpha: 1.0)
//scheme.onBackgroundColor = UIColor(red: 68.0/255.0, green: 44.0/255.0, blue: 46.0/255.0, alpha: 1.0)
//scheme.errorColor = UIColor(red: 197.0/255.0, green: 3.0/255.0, blue: 43.0/255.0, alpha: 1.0)
return scheme
}()
I want to make "Add to cart" button's border color same with "buy" button's color
You can use next color settings for creation MDCButton:
let myButton = MDCButton()
myButton.setTitle("Add to cart", for: .normal)
myButton.isUppercaseTitle = false
myButton.addTarget(self, action: #selector(myButtonAction(_:)), for: .touchUpInside)
myButton.frame = CGRect(x: 10, y: 10, width: 150, height: 40)
myButton.setBackgroundColor(UIColor.white)
myButton.setTitleColor(UIColor.blue, for: UIControl.State.normal)
myButton.setBorderColor(UIColor.lightGray, for: UIControl.State.normal)
myButton.setBorderWidth(1.0, for: UIControl.State.normal)
myButton.layer.cornerRadius = 5
view.addSubview(myButton)

Navigation Controller. Background color

For one controller I have settings:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
and
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
var offset = scrollView.contentOffset.y / 150
if offset > 1 {
offset = 1
self.navigationController?.navigationBar.backgroundColor = UIColor(red: 82/255, green: 76/255, blue: 70/255, alpha: offset)
UIApplication.shared.statusBarView?.backgroundColor = UIColor(red: 82/255, green: 76/255, blue: 70/255, alpha: offset)
self.navigationItem.title = name
} else {
self.navigationController?.navigationBar.backgroundColor = UIColor(red: 82/255, green: 76/255, blue: 70/255, alpha: offset)
UIApplication.shared.statusBarView?.backgroundColor = UIColor(red: 82/255, green: 76/255, blue: 70/255, alpha: offset)
self.navigationItem.title = ""
}
}
The main problem is that when i press back button, settings save. In the end i have white NavigationController. How can I make the settings not taken from the last controller?
func makeSearchController() {
searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.tintColor = .white
searchController.searchBar.placeholder = "Блюдо или продукт ..."
}
You can reset the navigation controller's color in viewWillDisappear, like this:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.navigationBar.backgroundColor = UIColor(red: 221/255, green: 221/255, blue: 225/255, alpha: offset) //gray color
UIApplication.shared.statusBarView?.backgroundColor = UIColor(red: 221/255, green: 221/255, blue: 225/255, alpha: offset) //gray color
}

Can't trigger action of a UIButton after modifying its UI

I create a UIButton which is displayed inside a XIB. But when I add a modification for the iPhone X display, I can't trigger the method inside its action. Here is the code below:
#IBOutlet weak var tryAgainButton: UIButton!
#IBAction func tryAgainButtonPressed(_ sender: UIButton) {
myFunction()
}
if UIDevice().userInterfaceIdiom == .phone, // Iphone X
UIScreen.main.nativeBounds.height == 2436 {
label.font = label.font.withSize(12)
contentView.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.top.equalToSuperview().offset(-20)
containerView.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
contentView.backgroundColor? = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
containerView.backgroundColor? = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
label.textColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
helpButton.setTitleColor(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1), for: .normal)
tryAgainButton.setTitleColor(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1), for: .normal)
let underlineAttributes : [NSAttributedStringKey: Any] = [
NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue,
NSAttributedStringKey.foregroundColor : #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
]
let helpButtonAttributeString = NSMutableAttributedString(string: "Help",
attributes: underlineAttributes)
let tryAgainButtonAttributeString = NSMutableAttributedString(string: "Try Again",
attributes: underlineAttributes)
helpButton.setAttributedTitle(helpButtonAttributeString, for: .normal)
tryAgainButton.setAttributedTitle(tryAgainButtonAttributeString, for: .normal)
}
}
myFunction() is not reachable when I run with an Iphone X.

If statement not working for triple digits?

So here's the simple problem.
if cell.count.text == "\(0)"
{
cell.pText.textColor = UIColor.grayColor()
cell.nicebutton!.setImage(UIImage(named:"defaulltup"), forState: UIControlState.Normal)
cell.nopebutton!.setImage(UIImage(named:"defaultdown"), forState: UIControlState.Normal)
cell.count.textColor = UIColor.grayColor()
cell.time.textColor = UIColor.grayColor()
}
if cell.count.text >= "\(1)"
{
cell.pText.textColor = UIColor.whiteColor()
//cell.time.textColor = UIColor(red: 42.0/255, green: 204.0/255, blue: 113.0/255, alpha: 1)
cell.count.textColor = UIColor(red: 42.0/255, green: 204.0/255, blue: 113.0/255, alpha: 1)
cell.nicebutton!.setImage(UIImage(named:"upgreen"), forState: UIControlState.Normal)
cell.nopebutton!.setImage(UIImage(named:"defaultdown"), forState: UIControlState.Normal)
//cell.nopebutton!.setImage(UIImage(named:"downred"), forState: UIControlState.Normal)
cell.count.textColor = UIColor(red: 42.0/255, green: 204.0/255, blue: 113.0/255, alpha: 1)
}
if cell.count.text < "\(0)"
{
cell.pText.textColor = UIColor(red: 231.0/255, green: 76.0/255, blue: 50.0/255, alpha: 1)
//cell.time.textColor = UIColor(red: 231.0/255, green: 76.0/255, blue: 50.0/255, alpha: 1)
cell.count.textColor = UIColor(red: 231.0/255, green: 76.0/255, blue: 50.0/255, alpha: 1)
cell.nicebutton!.setImage(UIImage(named:"defaulltup"), forState: UIControlState.Normal)
//cell.nicebutton!.setImage(UIImage(named:"upgreen"), forState: UIControlState.Normal)
cell.nopebutton!.setImage(UIImage(named:"downred"), forState: UIControlState.Normal)
}
if cell.count.text >= "\(99)"
{
cell.pText.textColor = UIColor(red: 249.0/255, green: 191.0/255, blue: 59.0/255, alpha: 1)
//cell.nopebutton!.setImage(UIImage(named:"downred"), forState: UIControlState.Normal)
cell.nicebutton!.setImage(UIImage(named:"golden"), forState: UIControlState.Normal)
cell.count.textColor = UIColor(red: 249.0/255, green: 191.0/255, blue: 59.0/255, alpha: 1)
}
The last if statement isn't working at ALL, while the others are working just as they should. I'm really confused as to why this is the case.
First of all, in your code you're comparing strings (not numbers contained in strings) using < and > operators. That is probably not what you want to do. According to the Swift docs:
For characters in strings, “greater than” means “appears later in the
alphabet than”
The comparison results for strings are different than if you just compared the numbers, so for example the expression "2" > "10" is true, while of course 2 > 10 is false.
If you want to compare the numbers contained in the strings, you can do this instead:
if cell.count.text.toInt() == 0
// etc.
Also, it would help you avoid bugs if you wrote your if conditions like this:
if condition1 {
//...
}
else if condition2 {
//...
}
else {
//...
}
In your current code, if one of the conditions is incorrect, more than one block of code can be executed for the same value of cell.count.text.
Your issue is that you are comparing strings and expecting them to behave the same as integers. Unfortunately, this is not the case. You can easily check this:
print("100" > "99")
You will get an output of False. As far as characters go, 9 comes after 1, so 99 is always greater than 100. My advice is to convert cell.count.text to an Int and then make your comparisons. Note that converting to an Int produces an Optional so you have to use if let to bind the value.
if let count = cell.count.text.toInt() {
if count < 0 {
// Do something useful here
}
if count > 99 {
// Do something useful here
}
}
else {
// Handle the case where cell.count.text isn't a valid integer
}
Move this code:
if cell.count.text >= 99
above:
if cell.count.text >= 1