索引数组中的最后一项不响应 UIPanGestureRecognizer
last item in index array not responsive to UIPanGestureRecognizer
我的 swift 下面的代码应该在调用该函数时添加图像视图。然后当按下它时应该四处移动。现在第一次按下按钮时,imageview 不起作用,但如果该函数被调用两次,第一个 imageview 移动。如果 func 被调用 3 次,则第一个和第二个图像视图移动,但第三个图像视图不移动。当图像视图放在屏幕上时,我希望它立即移动
import UIKit
class ViewController: UIViewController {
var myArray = [UIImageView]()
var bt = UIButton()
var count : Int = 0
var pgGesture = UIPanGestureRecognizer()
var ht = -90
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(bt)
bt.backgroundColor = UIColor.systemOrange
bt.frame = CGRect(x: view.center.x - 80, y: view.center.y , width: 50, height: 50)
bt.addTarget(self, action: #selector(add), for: .touchUpInside)
}
@objc func add() {
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))
for index in myArray.indices {
myArray[index].isUserInteractionEnabled = true
myArray[index].addGestureRecognizer(pgGesture)
myArray[index].tag = index
}
myArray.insert(UIImageView(), at: count)
myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 30)
myArray.forEach({
[=10=].backgroundColor = UIColor.systemTeal
self.view.addSubview([=10=])
})
count += 1
ht += 50
}
@objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
self.view.bringSubviewToFront(sender.view!)
let tranistioon = sender.translation(in: self.view)
sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
}
好的,你试试这个怎么样。这是我改变的:pgGesture 的声明现在是一个可选的(不需要两次初始化它,这是你在代码中所做的),将 pgGesture 的初始化移动到 ViewDidLoad 而不是它在 addFunction 内部(它只需要被初始化一次,而不是每次调用 add() 函数时都被初始化),最后(这就是你所看到的问题的原因),我在插入图像之前将 pgGesture 添加到图像中(之前你没有分配panGesture 到正在插入的图像,而不是数组的所有其他条目)。
import UIKit
class ViewController: UIViewController {
var myArray = [UIImageView]()
var bt = UIButton()
var count : Int = 0
var pgGesture: UIPanGestureRecognizer?
var ht = -90
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(bt)
bt.backgroundColor = UIColor.systemOrange
bt.frame = CGRect(x: view.center.x - 80, y: view.center.y , width: 50, height: 50)
bt.addTarget(self, action: #selector(add), for: .touchUpInside)
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))
}
@objc func add() {
for index in myArray.indices {
myArray[index].isUserInteractionEnabled = true
myArray[index].tag = index
}
let imageToInsert = UIImageView()
imageToInsert.addGestureRecognizer(pgGesture)
myArray.insert(UIImageView(), at: count)
myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 30)
myArray.forEach({
[=10=].backgroundColor = UIColor.systemTeal
self.view.addSubview([=10=])
})
count += 1
ht += 50
}
@objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
self.view.bringSubviewToFront(sender.view!)
let tranistioon = sender.translation(in: self.view)
sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
}
这里有几个问题:
您的手势识别器处理程序正在更新手势视图的 center
。显然,目的是将此手势添加到您要拖动的视图中。
所以这里的主要问题是您将手势识别器添加到错误的视图中。您应该将其添加到青色可拖动视图中,但您将其添加到主视图中。
这无关紧要,但是 add
方法做了很多不必要的事情。假设您要添加第 100 个新的蓝绿色子视图。你为什么还要重新更新之前的99个子视图?
只需配置要添加的视图并摆脱那些不必要的 for
/forEach
循环。
同样,无关,但我建议在使用 center
时要小心。这是相关视图在其父视图中的位置。因此,当向视图控制器的 view
添加按钮和蓝绿色子视图时,您应该引用 view.bounds.midX
和 .midY
,而不是 view.center
。因为视图占据了整个屏幕,所以你不会真正看到差异,但是如果视图控制器是另一个视图的子视图控制器,那么就会有天壤之别。
因此:
class ViewController: UIViewController {
// var mySubviews = [UIImageView]()
var addButton = UIButton()
var count: Int = 0
var ht = -90
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(addButton)
addButton.backgroundColor = .systemOrange
addButton.addTarget(self, action: #selector(didTapAdd(_:)), for: .touchUpInside)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addButton.frame = CGRect(x: view.bounds.midX - 80, y: view.bounds.midY, width: 50, height: 50)
}
@objc func didTapAdd(_ sender: UIButton) {
let subview = UIImageView()
subview.isUserInteractionEnabled = true
view.addSubview(subview)
subview.frame = CGRect(x: view.bounds.midX - 0, y: view.bounds.midY + CGFloat(ht), width: 50, height: 30)
subview.backgroundColor = .systemTeal
subview.tag = count
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
subview.addGestureRecognizer(pan)
count += 1
ht += 50
// mySubviews.append(subview)
}
@objc func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
let draggedView = gesture.view!
view.bringSubviewToFront(draggedView)
let translation = gesture.translation(in: view)
draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
}
一些最后的观察:
我不鼓励使用 tag
。用于诊断目的没问题,但仅此而已。
在我的代码片段中,我还注释掉了声明并附加到子视图数组,因为它完全没有必要。
请见谅,我已经重命名了方法和变量。
我不确定你为什么要使用 UIImageView
。我个人会使用 UIView
除非你真的打算在以后最终添加图像。
如果您要对按钮的 frame
进行硬编码,则不能在 viewDidLoad
中执行此操作(因为视图尚未布局)。如果您要设置 frame
,则需要在 viewDidLayoutSubviews
中进行设置。您可以在 viewDidLoad
中设置约束,但不能在框架中设置约束。
我的 swift 下面的代码应该在调用该函数时添加图像视图。然后当按下它时应该四处移动。现在第一次按下按钮时,imageview 不起作用,但如果该函数被调用两次,第一个 imageview 移动。如果 func 被调用 3 次,则第一个和第二个图像视图移动,但第三个图像视图不移动。当图像视图放在屏幕上时,我希望它立即移动
import UIKit
class ViewController: UIViewController {
var myArray = [UIImageView]()
var bt = UIButton()
var count : Int = 0
var pgGesture = UIPanGestureRecognizer()
var ht = -90
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(bt)
bt.backgroundColor = UIColor.systemOrange
bt.frame = CGRect(x: view.center.x - 80, y: view.center.y , width: 50, height: 50)
bt.addTarget(self, action: #selector(add), for: .touchUpInside)
}
@objc func add() {
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))
for index in myArray.indices {
myArray[index].isUserInteractionEnabled = true
myArray[index].addGestureRecognizer(pgGesture)
myArray[index].tag = index
}
myArray.insert(UIImageView(), at: count)
myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 30)
myArray.forEach({
[=10=].backgroundColor = UIColor.systemTeal
self.view.addSubview([=10=])
})
count += 1
ht += 50
}
@objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
self.view.bringSubviewToFront(sender.view!)
let tranistioon = sender.translation(in: self.view)
sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
}
好的,你试试这个怎么样。这是我改变的:pgGesture 的声明现在是一个可选的(不需要两次初始化它,这是你在代码中所做的),将 pgGesture 的初始化移动到 ViewDidLoad 而不是它在 addFunction 内部(它只需要被初始化一次,而不是每次调用 add() 函数时都被初始化),最后(这就是你所看到的问题的原因),我在插入图像之前将 pgGesture 添加到图像中(之前你没有分配panGesture 到正在插入的图像,而不是数组的所有其他条目)。
import UIKit
class ViewController: UIViewController {
var myArray = [UIImageView]()
var bt = UIButton()
var count : Int = 0
var pgGesture: UIPanGestureRecognizer?
var ht = -90
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(bt)
bt.backgroundColor = UIColor.systemOrange
bt.frame = CGRect(x: view.center.x - 80, y: view.center.y , width: 50, height: 50)
bt.addTarget(self, action: #selector(add), for: .touchUpInside)
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))
}
@objc func add() {
for index in myArray.indices {
myArray[index].isUserInteractionEnabled = true
myArray[index].tag = index
}
let imageToInsert = UIImageView()
imageToInsert.addGestureRecognizer(pgGesture)
myArray.insert(UIImageView(), at: count)
myArray[count].frame = CGRect(x: view.center.x - 0, y: view.center.y + CGFloat(ht), width: 50, height: 30)
myArray.forEach({
[=10=].backgroundColor = UIColor.systemTeal
self.view.addSubview([=10=])
})
count += 1
ht += 50
}
@objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
self.view.bringSubviewToFront(sender.view!)
let tranistioon = sender.translation(in: self.view)
sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
}
这里有几个问题:
您的手势识别器处理程序正在更新手势视图的
center
。显然,目的是将此手势添加到您要拖动的视图中。所以这里的主要问题是您将手势识别器添加到错误的视图中。您应该将其添加到青色可拖动视图中,但您将其添加到主视图中。
这无关紧要,但是
add
方法做了很多不必要的事情。假设您要添加第 100 个新的蓝绿色子视图。你为什么还要重新更新之前的99个子视图?只需配置要添加的视图并摆脱那些不必要的
for
/forEach
循环。同样,无关,但我建议在使用
center
时要小心。这是相关视图在其父视图中的位置。因此,当向视图控制器的view
添加按钮和蓝绿色子视图时,您应该引用view.bounds.midX
和.midY
,而不是view.center
。因为视图占据了整个屏幕,所以你不会真正看到差异,但是如果视图控制器是另一个视图的子视图控制器,那么就会有天壤之别。
因此:
class ViewController: UIViewController {
// var mySubviews = [UIImageView]()
var addButton = UIButton()
var count: Int = 0
var ht = -90
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(addButton)
addButton.backgroundColor = .systemOrange
addButton.addTarget(self, action: #selector(didTapAdd(_:)), for: .touchUpInside)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addButton.frame = CGRect(x: view.bounds.midX - 80, y: view.bounds.midY, width: 50, height: 50)
}
@objc func didTapAdd(_ sender: UIButton) {
let subview = UIImageView()
subview.isUserInteractionEnabled = true
view.addSubview(subview)
subview.frame = CGRect(x: view.bounds.midX - 0, y: view.bounds.midY + CGFloat(ht), width: 50, height: 30)
subview.backgroundColor = .systemTeal
subview.tag = count
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
subview.addGestureRecognizer(pan)
count += 1
ht += 50
// mySubviews.append(subview)
}
@objc func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
let draggedView = gesture.view!
view.bringSubviewToFront(draggedView)
let translation = gesture.translation(in: view)
draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
}
一些最后的观察:
我不鼓励使用
tag
。用于诊断目的没问题,但仅此而已。在我的代码片段中,我还注释掉了声明并附加到子视图数组,因为它完全没有必要。
请见谅,我已经重命名了方法和变量。
我不确定你为什么要使用
UIImageView
。我个人会使用UIView
除非你真的打算在以后最终添加图像。如果您要对按钮的
frame
进行硬编码,则不能在viewDidLoad
中执行此操作(因为视图尚未布局)。如果您要设置frame
,则需要在viewDidLayoutSubviews
中进行设置。您可以在viewDidLoad
中设置约束,但不能在框架中设置约束。