Swift - UIStackView 中的 UIPanRecognizer
Swift - UIPanRecognizer in a UIStackView
我想在 UIStackView 中创建一个 UIPanRecognizer。 The UI looks like this.
有一个大方块,它是一个包含 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 就是一场噩梦)。
我将不胜感激任何帮助。谢谢。
编辑:可能这个有帮助?
每个标签都是其包含堆栈视图的子视图(也可能是堆栈视图的子视图),并且每个标签都有自己的坐标 space.
假设您的 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
}
}
}
}
我想在 UIStackView 中创建一个 UIPanRecognizer。 The UI looks like this.
有一个大方块,它是一个包含 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 就是一场噩梦)。
我将不胜感激任何帮助。谢谢。
编辑:可能这个有帮助?
每个标签都是其包含堆栈视图的子视图(也可能是堆栈视图的子视图),并且每个标签都有自己的坐标 space.
假设您的 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
}
}
}
}