我在水平UIButtons
内有两个UIStackView
。我想添加一个UIView
作为子视图,这样当我按下其中一个按钮时,视图会水平移动到所选按钮。
我有这段代码:
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
}
当视图添加到左侧按钮时,此代码实际上有效。单击按钮时,视图将从左向右和从右向左移动。
但如果我选择右键开始:
let selectionView = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 19))
selectionView.backgroundColor = UIColor.redColor()
self.expensiveButton.addSubview(selectionView) // right button
视图仅更改颜色,但不会从右向左移动。
为什么?如何修复我的代码以便可以以任何方式移动视图?
UPDATE
:
我尝试在UIView
中添加堆栈视图,并在其中添加selectionView。这是一个快照:
当我选择正确的按钮运行应用程序时仍然有问题,selectionView出现在containerView之外(它应该出现在Expensive文本的右侧):
当我检查应该选择哪个按钮时,这是viewDidLoad
内的代码:
if type == .Income {
self.selectionView.backgroundColor = UIColor(hex: "28BB9D")
self.selectionView.center = self.incomeButton.center
} else {
self.selectionView.backgroundColor = UIColor(hex: "E5344A")
}
UPDATE 2:
selectionView的当前约束:
答案 0 :(得分:2)
<强>目标强>:
以编程方式创建 selectionView
,以便在孩提时间切换两个UIButton
。
为了更好地解释我已添加(开始)selectionView
到expensiveButton
(您遇到问题的按钮......)的情况。
您可以在项目中进行一些更正,以确保其运作良好。
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)
}
}
}
一些解释:
首先,在您的项目中,您不会报告selectView
的全局引用,但我认为您只是忘记在您的问题中写下它。
所以,一个好处是为你的selectionView设置一个标签,就像一个id号码,可以在他未来的父视图的子视图之间识别它(在你的情况下它将是UIButton
)
正如您所看到的,我添加了viewDidAppear
方法,为什么?因为当你在viewDidLoad
时你的按钮没有完全准备好,所以你的中心错误,当你的视图最终被绘制时,获得这个值的正确位置是viewDidAppear
。
现在让我们来谈谈selectionView
:它是一个视图,因此您可以将其添加到incomeButton
但是如果您已将其添加到另一个按钮中,则必须将其删除来自expensiveButton只需这一行:
self.expensiveButton.viewWithTag(666)?.removeFromSuperview()
最后的中心点:记住你在自动布局中,所以找到它的好方法可以是使用边界:
self.selectionView.center = CGPointMake(self.expensiveButton.bounds.midX, self.expensiveButton.bounds.midY)
这是我的项目结构,我看到你正在研究它:
<强>更新强>:
在我看到您的更新后(您开始使用selectionView
以编程方式创建)有关您的问题的一些评论和回答,我怀疑您想要实现自定义{{1} }。我认为使用UISegmentedControl
来实现一点点控制并不是一个好主意,你可以在UIStackView
周围发现许多项目UISegmentedControl
,例如BetterSegmentedControl }:
代码示例:
UIControl
图片:
答案 1 :(得分:0)
这里的关键问题是坐标系。您正在将selectionView添加为一个按钮或另一个按钮的子视图,但由于它在两者之间移动,因此它实际上应该是两个按钮的某些祖先视图的子视图。
当您更改selectionView中心时,它会相对于其超级视图设置其位置的动画,当前代码中的位置是左按钮或右按钮。从左到右动画起作用,因为右按钮的中心是一些坐标,其x值大于selectionView在左按钮坐标空间内的值。但是当您从右侧按钮的坐标空间内的selectionView开始时,左侧按钮的中心相对于其自己的超级视图可能非常接近selectionView的中心相对于右侧按钮的坐标空间。所以没有真正的动作。
如果您这样想的话,这可能更容易想象:为了从右侧按钮的坐标空间移动到左按钮的位置,selectionView的中心x将需要是一个负数,因为它需要留在右键的前沿。但是,左侧按钮相对于其自身超级视图的中心具有正x值。因此,如果选择视图中心位于右侧按钮的坐标空间内,则将其设置为左侧按钮的中心将永远不会向左移动。
通过将选择视图添加到两个按钮所在的同一超视图中,您可以成功使用动画中的中心坐标,因为所有三个视图(2个按钮和selectionView)将位于相同的坐标空间中。
如果2个按钮位于堆栈视图中,这可能会有点麻烦,因为您不想手动设置堆栈视图排列的内容。在这种情况下,解决方案是将堆栈视图包装在普通的UIView中,并在堆栈视图前面添加selectionView,作为同一个普通UIView的子项。
只要堆栈视图框架与包含UIView的边界匹配,它仍然可以正常工作,以便在左按钮中心和右按钮中心之间为selectionView的中心设置动画。
使用以下视图层次结构,您的代码将起作用:
containerView
|____ selectionView
|____ stackView
|_______ leftButton
|_______ rightButton
答案 2 :(得分:0)
这是我的解决方案。 我做了以下视图和约束安排:
选择视图具有以下约束:
在4个约束中,第一个约束(将中心X对齐到堆栈视图)是视图控制器。 总奥特莱斯如下:
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var selectionView: UIView!
@IBOutlet weak var selectionviewCenterCon: NSLayoutConstraint!
@IBOutlet weak var expensiveBtn: UIButton!
@IBOutlet weak var incomeBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.selectionView.backgroundColor = UIColor.redColor()
self.selectionviewCenterCon.constant = -stackView.frame.size.width / 4
}
@IBAction func expensiveBtnClicked(sender: AnyObject) {
self.selectionviewCenterCon.constant = -stackView.frame.size.width / 4
UIView.animateWithDuration(0.3) {
self.selectionView.backgroundColor = UIColor.redColor()
self.view.layoutIfNeeded()
}
}
@IBAction func incomeBtnClicked(sender: AnyObject) {
self.selectionviewCenterCon.constant = stackView.frame.size.width / 4
UIView.animateWithDuration(0.3) {
self.selectionView.backgroundColor = UIColor.greenColor()
self.view.layoutIfNeeded()
}
}
此代码将输出显示为: