我想打一个UIPanRecognizer在UIStackView。 该UI看起来是这样的。
有一个大的广场,是包含9个标签一个StackView。 我的目标是当我开始在StackView内拖我的手指,如果一个标签包含一个接触点,然后它的颜色应该是蓝色和和。 如果我抬起我的手指所有的标签背景色变成回白色。
标签是在OutletCollection。
这里是我的代码:
@IBOutlet var testLabels: [UILabel]!
@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
var touchedPoint: CGPoint!
if let view = recognizer.view{
if recognizer.state == .began || recognizer.state == .changed {
touchedPoint = recognizer.location(in: view)
for index in testLabels.indices {
if testLabels[index].frame.contains(touchedPoint) {
testLabels[index].backgroundColor = UIColor.blue
}
}
}
if recognizer.state == .ended {
for index in testLabels.indices {
testLabels[index].backgroundColor = UIColor.white
}
}
}
现在,当我触摸例如左上角方形,并开始我的手指向右拖动整个第一栏将变为蓝色,然后第二个,然后第三。 发生这种情况时,我接触到第一行的任何标签,但是当我接触到其他的广场没有任何反应。
第一次,我试图通过处理方块只是作为一个OutletCollection解决我的问题(不StackView)和识别只是工作罚款! 为什么我用StackView实验,它是如此容易使布局的原因(需要短短的约束,没有StackView它是一场噩梦)。
我会很感激的任何帮助。 谢谢。
编辑:这可能是一个帮助?
访问嵌套的堆栈意见
每个标签是其含有堆栈视图(这也是可能的堆叠视图的子视图)的子视图,并且每个标签具有其自己的坐标空间。
假设你UIPanGestureRecognizer
被分配到视图控制器的视图,你需要的坐标转换/帧。
这应该为你工作:
@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
var touchedPoint: CGPoint!
if let view = recognizer.view{
if recognizer.state == .began || recognizer.state == .changed {
touchedPoint = recognizer.location(in: view)
for index in testLabels.indices {
// translate / convert the label's bounds from its frame to the view's coordinate space
let testFrame = view.convert(testLabels[index].bounds, from:testLabels[index] )
// check the resulting testFrame for the point
if testFrame.contains(touchedPoint) {
testLabels[index].backgroundColor = UIColor.blue
}
}
}
else if recognizer.state == .ended {
for index in testLabels.indices {
testLabels[index].backgroundColor = UIColor.white
}
}
}
}
您也可以通过简化您的代码位for object in collection
,而不是指数。 这在功能上与上面相同,但也许有点简单:
@IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
var touchedPoint: CGPoint!
if let view = recognizer.view{
if recognizer.state == .began || recognizer.state == .changed {
touchedPoint = recognizer.location(in: view)
for lbl in testLabels {
// translate / convert the label's bounds from its frame to the view's coordinate space
let testFrame = view.convert(lbl.bounds, from:lbl )
// check the resulting testFrame for the point
if testFrame.contains(touchedPoint) {
lbl.backgroundColor = .blue
}
}
}
else if recognizer.state == .ended {
for lbl in testLabels {
lbl.backgroundColor = .white
}
}
}
}