0

I want to programmatically set multiple alignment combinations for my button title, like so: enter image description here The easiest way I found to do this was to add two UILabels as subviews of my custom UIButton and set autolayout constraints accordingly.

However, I can't figure out how to make my labels behave the same way as a button title would (namely having its alpha altered when a button tap occurs).

I have tried setting their alpha property in a target-action method for .touchUpInside but since they're not attached to the button state, they won't change their alpha back to normal when the user ends tapping the button.

class Button: UIView {

var leftButton = UIButton(type: .roundedRect)
var rightButton = UIButton(type: .roundedRect)

init() {
    super.init(frame: .zero)
    createButton()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    createButton()
}

func createButton() {
    self.backgroundColor = UIColor.cyan
    self.layer.borderWidth = 0.5
    self.layer.borderColor = UIColor.blue.cgColor
    self.addSubview(leftButton)
    self.addSubview(rightButton)

    leftButton.setTitle("left", for: .normal)
    leftButton.setTitleColor(UIColor.black, for: .normal)
    leftButton.layer.borderColor = UIColor.yellow.cgColor
    leftButton.layer.borderWidth = 0.5
    leftButton.translatesAutoresizingMaskIntoConstraints = false
    leftButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
    leftButton.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    leftButton.trailingAnchor.constraint(lessThanOrEqualTo: rightButton.leadingAnchor).isActive = true
    leftButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true

    rightButton.setTitle("right", for: .normal)
    rightButton.layer.borderColor = UIColor.green.cgColor
    rightButton.layer.borderWidth = 0.5
    rightButton.setTitleColor(UIColor.black, for: .normal)
    rightButton.translatesAutoresizingMaskIntoConstraints = false
    rightButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
    rightButton.leadingAnchor.constraint(greaterThanOrEqualTo: leftButton.trailingAnchor).isActive = true
    rightButton.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
    rightButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true

    leftButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
    rightButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}

func buttonTapped() {
    print("button tapped")
}
rikesan
  • 153
  • 1
  • 7

3 Answers3

1

there is a better approach.

Take two buttons and keep them in a stackView and do necessary settings.

But make sure that two buttons will point to same action.So that it will seem to user that it's actually one button.

here is the output.

enter image description here

I just made this in storyboard. As i am using stackView so programmatically creating and layouting is super easy. I think you can do it. :)

To stop flashing:

Make each button type custom.

How to make only one button action for both button?

See this popular stack answer.

Here is the result.

enter image description here

elk_cloner
  • 2,049
  • 1
  • 12
  • 13
  • I have tried your approach and updated the original post with the current code but that did not work. When you say 'point to the same action' you mean the same function receiving the touchUpInside action for both buttons? – rikesan Jun 07 '17 at 20:25
  • 1
    While this approach would work the problem is tapping on the left button would show the 'flash' action that a button has but the right one wouldn't so that would look a little strange if they are supposed to act like a single button. If you can live with that then it should work fine. – Upholder Of Truth Jun 07 '17 at 20:34
  • Indeed. I need both buttons to have the same effect simultaneously. – rikesan Jun 07 '17 at 20:36
  • use UIButtonTypeCustom to stop flashing. – elk_cloner Jun 07 '17 at 22:20
0

What you need is to differentiate between tap and hold and release of the button states. Luckily there are 2 built-in action methods that we can make use of for this.

  • Touch Down Action: This will be called as soon as you tap on the button. So you can change the alpha of your labels here.

  • Touch Up Inside: This action method is called when you have released the button. So you can reset your alpha here.

    @IBAction func touchupInsideAction(_ sender: Any) {
    
        firstLabel.alpha = 1.0
        secondLabel.alpha = 1.0
    }
    
    @IBAction func touchDownAction(_ sender: Any) {
    
        firstLabel.alpha = 0.5
        secondLabel.alpha = 0.5
    
    }
    

enter image description here

Zarif Ahmed
  • 343
  • 2
  • 9
0

I was able to put the two labels and get them highlighted when clicked by creating a UIButton other than .custom (for this example I used .roundedRect), setting a dummy title, adding subviews to the button title itself and setting their constraints as I wanted to. It works as expected.

Code:

class Button: UIView {

let button: UIButton
let leftLabel = UILabel()
let rightLabel = UILabel()

init() {
    button = UIButton(type: .roundedRect)
    super.init(frame: .zero)
    createButton()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func createButton() {
    self.addSubview(button)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    button.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    button.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    button.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true

    button.backgroundColor = UIColor.cyan
    button.layer.borderWidth = 0.5
    button.layer.borderColor = UIColor.blue.cgColor
    button.setTitle(" ", for: .normal)

    if let title = button.titleLabel {
        title.addSubview(rightLabel)
        rightLabel.text = "right"
        rightLabel.translatesAutoresizingMaskIntoConstraints = false
        rightLabel.topAnchor.constraint(equalTo: title.topAnchor).isActive = true
        rightLabel.leadingAnchor.constraint(greaterThanOrEqualTo: title.trailingAnchor).isActive = true
        rightLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        rightLabel.bottomAnchor.constraint(equalTo: title.bottomAnchor).isActive = true

        title.addSubview(leftLabel)
        leftLabel.text = "left"
        leftLabel.translatesAutoresizingMaskIntoConstraints = false
        leftLabel.topAnchor.constraint(equalTo: title.topAnchor).isActive = true
        leftLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        leftLabel.trailingAnchor.constraint(lessThanOrEqualTo: title.leadingAnchor).isActive = true
        leftLabel.bottomAnchor.constraint(equalTo: title.bottomAnchor).isActive = true
    }

    button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
}

func buttonTapped() {
    print("button tapped")
}
rikesan
  • 153
  • 1
  • 7