I want to make my blue underline start and end within the red frame. So, I'm trying to get the X position, the starting position of my UIButton. The red one (red is a bg color). How can I do that?
Things I've tried:
promoButton.frame.origin.x
or
promoButton.bounds.origin.x
result: 0.0
promoButton.layer.position.x
This actually move the underline, but it started at the 'P' of 'Promo' instead of the red frame.
Can anyone tell me how to get the frame X position?
Thankyou in advance.
Update:
This is how i put it in the storyboard:
First there is this Tab View
Next, I have the container
Then the Promo button it self
I guess 0.0 is because it's inside a view. but is it possible to calculate X position from the screen tho?
You can do this with auto-layout / constraints, so you don't need to worry about "frames."
We'll setup the Storyboard like this - note: we are NOT adding the "underline view" in the Storyboard:
I've given the "container view" and the buttons different background colors to make it easier to see the framing.
We'll make @IBOutlet
connections to the three buttons:
@IBOutlet var btn1: UIButton!
@IBOutlet var btn2: UIButton!
@IBOutlet var btn3: UIButton!
and we'll connect the Touch Up Inside
for all buttons to the same function.
In viewDidLoad()
we'll create and add the underlineView
, and give it a Height
constraint of 4.0
. It looks like you want it about 8-points below the buttons, so we'll also give it a Top
constraint relative to the Bottom of the first button (doesn't really matter which button, as we're assuming they are the same).
Now, we'll add two class properties:
var underlineLeadingConstraint: NSLayoutConstraint!
var underlineWidthConstraint: NSLayoutConstraint!
Again in viewDidLoad()
we'll create those two constraints, and set them related to btn1
.
When we tap a button, we'll:
deactivate those two constraints
re-make them related to the tapped button
and animate the change
@IBAction func btnTap(_ sender: UIButton) { // de-activate the underline view constraints underlineLeadingConstraint.isActive = false underlineWidthConstraint.isActive = false
// re-create the Leading and Width constraints
// related to the tapped button
underlineLeadingConstraint = underlineView.leadingAnchor.constraint(equalTo: sender.leadingAnchor)
underlineWidthConstraint = underlineView.widthAnchor.constraint(equalTo: sender.widthAnchor)
// activate those new constraints
underlineLeadingConstraint.isActive = true
underlineWidthConstraint.isActive = true
// if you want to animate it
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
}
Here's the complete controller class:
class UnderlineViewController: UIViewController {
@IBOutlet var btn1: UIButton!
@IBOutlet var btn2: UIButton!
@IBOutlet var btn3: UIButton!
var underlineView: UIView!
var underlineLeadingConstraint: NSLayoutConstraint!
var underlineWidthConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
underlineView = UIView()
underlineView.backgroundColor = .blue
underlineView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(underlineView)
// underlineView height is 4-points
underlineView.heightAnchor.constraint(equalToConstant: 4.0).isActive = true
// looks like you want it about 8-points below the button bottom?
underlineView.topAnchor.constraint(equalTo: btn1.bottomAnchor, constant: 8.0).isActive = true
// create Leading and Width constraints for the underlineView
underlineLeadingConstraint = underlineView.leadingAnchor.constraint(equalTo: btn1.leadingAnchor)
underlineWidthConstraint = underlineView.widthAnchor.constraint(equalTo: btn1.widthAnchor)
// activate those constraints
underlineLeadingConstraint.isActive = true
underlineWidthConstraint.isActive = true
}
@IBAction func btnTap(_ sender: UIButton) {
// de-activate the underline view constraints
underlineLeadingConstraint.isActive = false
underlineWidthConstraint.isActive = false
// re-create the Leading and Width constraints
// related to the tapped button
underlineLeadingConstraint = underlineView.leadingAnchor.constraint(equalTo: sender.leadingAnchor)
underlineWidthConstraint = underlineView.widthAnchor.constraint(equalTo: sender.widthAnchor)
// activate those new constraints
underlineLeadingConstraint.isActive = true
underlineWidthConstraint.isActive = true
// if you want to animate it
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
}
}
Here's how it looks when running:
Since we are now using constraints - instead of calculating frame coordinates - the underline width and position will automatically update when the "tab buttons" change... such as on device rotation.