I have two UIButtons
inside an horizontal UIStackView
. I want to add a UIView
as a subview so that when I press one of the buttons, the view moves horizontally to the selected button.
I have this code:
let selectionView = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 19))
selectionView.backgroundColor = UIColor.greenColor()
self.incomeButton.addSubview(selectionView) // left button
// left button touched
@IBAction func incomeDidTouch(sender: AnyObject) {
self.incomeButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
self.expensiveButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
UIView.animateWithDuration(0.3) {
self.selectionView.backgroundColor = UIColor.greenColor()
self.selectionView.center = self.incomeButton.center
}
}
// right button touched
@IBAction func expensiveDidTouch(sender: AnyObject) {
self.expensiveButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
self.incomeButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
UIView.animateWithDuration(0.3) {
self.selectionView.backgroundColor = UIColor.redColor()
self.selectionView.center = self.expensiveButton.center
}
This code actually works when the view is added to the left button. The view will move from left to right and right to left when clicking the buttons.
But if I start with the right button selected:
let selectionView = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 19))
selectionView.backgroundColor = UIColor.redColor()
self.expensiveButton.addSubview(selectionView) // right button
The view only changes the color, but doesn't move from right to left.
Why is that ? How can I fix my code so that the view can be moved either way ?
UPDATE
:
I tried adding the stack view inside an UIView
and also add the selectionView inside it. Here is a snapshot:
I still have a problem when I run the app with the right button selected, the selectionView appears outside of the containerView (it should appear on the right side of the Expensive text):
This is the code inside viewDidLoad
when I check which button should be selected:
if type == .Income {
self.selectionView.backgroundColor = UIColor(hex: "28BB9D")
self.selectionView.center = self.incomeButton.center
} else {
self.selectionView.backgroundColor = UIColor(hex: "E5344A")
}
UPDATE 2:
Current constraints for selectionView:
Objective:
Create programmatically a selectionView
to switch throught two UIButton
as a child.
To explain better the situation I've added (to start) the selectionView
to expensiveButton
(the button where you have the issue..)
There are some corrections you could be do in your project to see it working well.
class ViewController: UIViewController {
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var incomeButton: UIButton!
@IBOutlet weak var expensiveButton: UIButton!
var selectionView : UIView!
override func viewDidLoad() {
super.viewDidLoad()
selectionView = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 19))
selectionView.backgroundColor = UIColor.greenColor()
selectionView.tag = 666
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.expensiveButton.addSubview(selectionView)
self.selectionView.backgroundColor = UIColor.redColor()
self.selectionView.center = CGPointMake(self.expensiveButton.bounds.midX, self.expensiveButton.bounds.midY)
}
@IBAction func incomeDidTouch(sender: AnyObject) {
if let _ = sender.viewWithTag(666) {} else {
self.incomeButton.addSubview(selectionView)
}
self.expensiveButton.viewWithTag(666)?.removeFromSuperview()
self.incomeButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
self.expensiveButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
UIView.animateWithDuration(0.3) {
self.selectionView.backgroundColor = UIColor.greenColor()
self.selectionView.center = CGPointMake(self.incomeButton.bounds.midX, self.incomeButton.bounds.midY)
}
}
@IBAction func expensiveDidTouch(sender: AnyObject) {
if let _ = sender.viewWithTag(666) {} else {
self.expensiveButton.addSubview(selectionView)
}
self.incomeButton.viewWithTag(666)?.removeFromSuperview()
self.expensiveButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
self.incomeButton.setTitleColor(UIColor.grayColor(), forState: .Normal)
UIView.animateWithDuration(0.3) {
self.selectionView.backgroundColor = UIColor.redColor()
self.selectionView.center = CGPointMake(self.expensiveButton.bounds.midX, self.expensiveButton.bounds.midY)
}
}
}
Some explaination:
First of all in your project you don't report a global reference to selectView
but I think you simply forgot to write it in your question.
So, a good thing is to set a tag to your selectionView, like an id number to can identify it between subviews of his future parent view (in your case it will be a UIButton
)
As you can see I've added the viewDidAppear
method, why? Because when you are in viewDidLoad
your button are not completly ready, so you have a wrong center, the right place to have this value is viewDidAppear
when your view is finally painted.
Now let's speaking about selectionView
: it's a view, so you can add it to incomeButton
but if you already have added it in the other button you must remove it from expensiveButton simply with this line:
self.expensiveButton.viewWithTag(666)?.removeFromSuperview()
Finally the center point: remember you are in autolayout so a good way to find it could be by using bounds:
self.selectionView.center = CGPointMake(self.expensiveButton.bounds.midX, self.expensiveButton.bounds.midY)
This is my project structure , I see you working on it:
Update:
After I've seen your updates (you started with a selectionView
created programmatically) some comments and answer about your issue, I've a suspicious you want to realize a custom UISegmentedControl
. I think using UIStackView
to realize a little control like it it's not a good idea, you can find many project around UISegmentedControl
that subclass UIControl
like for example BetterSegmentedControl:
A code example:
let control = BetterSegmentedControl(
frame: CGRect(x: 0.0, y: 100.0, width: view.bounds.width, height: 44.0),
titles: ["One", "Two", "Three"],
index: 1,
backgroundColor: UIColor(red:0.11, green:0.12, blue:0.13, alpha:1.00),
titleColor: .whiteColor(),
indicatorViewBackgroundColor: UIColor(red:0.55, green:0.26, blue:0.86, alpha:1.00),
selectedTitleColor: .blackColor())
control.titleFont = UIFont(name: "HelveticaNeue", size: 14.0)!
control.selectedTitleFont = UIFont(name: "HelveticaNeue-Medium", size: 14.0)!
control.addTarget(self, action: #selector(ViewController.controlValueChanged(_:)), forControlEvents: .ValueChanged)
view.addSubview(control)
A picture:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With