(Swift) UIPanGestureRecognizer 在添加子视图之前在视图上工作正常
(Swift) UIPanGestureRecognizer works fine on view until subview is added to it
我有以下视图(它是整体视图控制器的子视图):
lazy var superView: UIView = {
let cv = UIView()
cv.backgroundColor = .gray
cv.translatesAutoresizingMaskIntoConstraints = false
cv.layer.cornerRadius = 5
cv.layer.masksToBounds = true
cv.isUserInteractionEnabled = true
cv.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan)))
return cv
}()
这里是我为其设置约束的地方:
// constraints for super view
func setupSuperView() {
superView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
superView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
superView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
superView.heightAnchor.constraint(equalTo: view.heightAnchor, constant: -200).isActive = true
// ISSUE: For some reason, adding this subview with or without constraints screws up the pan functionality of the superview
superView.addSubview(subView)
}
这是我添加到 superView 内部的子视图(我将其视为容器视图):
lazy var subview: UIImageView = {
let sv = UIImageView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.contentMode = .scaleAspectFill
return sv
}()
及其约束条件:
// constraints for yes/no view within superview
func setupSubView() {
subView.centerXAnchor.constraint(equalTo: superView.centerXAnchor).isActive = true
subView.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true
}
最后,我在这里建立平移手势的功能:
// pan functionality for swiping on superview
func handlePan(gesture: UIPanGestureRecognizer) {
guard let superview = gesture.view else {
return
}
// point you are tapped on
let point = gesture.translation(in: view)
// reference for how far left or right of the center of the superview your pan is
let xFromCenter = superview.center.x - view.center.x
// allows the superview to move with your finger
superview.center = CGPoint(x: view.center.x + point.x, y: view.center.y + point.y)
// dragged right
if xFromCenter > 0 {
subView.image = #imageLiteral(resourceName: "yes")
subView.tintColor = UIColor.green
// else dragged left
} else {
subView.image = #imageLiteral(resourceName: "no")
subView.tintColor = UIColor.red
}
// when you let go
if gesture.state == UIGestureRecognizerState.ended {
// animate superview back to center where it originally was
UIView.animate(withDuration: 0.2) {
superview.center = self.view.center
}
}
}
在我添加子视图之前(以及当我将其注释掉时),平移手势在超级视图上工作得很好。但是,当我将子视图限制在超级视图的中心并尝试在视图控制器周围移动超级视图时,它的行为很奇怪(只正确地向左移动,向右移动时不断地回到中心)。
非常感谢任何帮助。
在您的子视图上禁用 userinteraction
,我认为它会起作用!
你的代码应该是这样的,
subView.isUserInteractionEnabled = false
我想通了这个问题。虽然我不知道这是修复的原因,但问题在于我用于向左平移容器视图的 "no" 选项的图像导致整个视图行为异常,因为它是不同的图像。
无论您是向左还是向右平移视图,我都通过设置两个选项 "yes" 来对此进行了测试。这解决了让我相信问题是图像根据您是向左滑动还是向右滑动而切换的问题。我不知道为什么它在显示两个不同的图像时会出现问题,但我也会尝试解决这个问题。
感谢您提供的所有有用信息!
我有以下视图(它是整体视图控制器的子视图):
lazy var superView: UIView = {
let cv = UIView()
cv.backgroundColor = .gray
cv.translatesAutoresizingMaskIntoConstraints = false
cv.layer.cornerRadius = 5
cv.layer.masksToBounds = true
cv.isUserInteractionEnabled = true
cv.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan)))
return cv
}()
这里是我为其设置约束的地方:
// constraints for super view
func setupSuperView() {
superView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
superView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
superView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
superView.heightAnchor.constraint(equalTo: view.heightAnchor, constant: -200).isActive = true
// ISSUE: For some reason, adding this subview with or without constraints screws up the pan functionality of the superview
superView.addSubview(subView)
}
这是我添加到 superView 内部的子视图(我将其视为容器视图):
lazy var subview: UIImageView = {
let sv = UIImageView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.contentMode = .scaleAspectFill
return sv
}()
及其约束条件:
// constraints for yes/no view within superview
func setupSubView() {
subView.centerXAnchor.constraint(equalTo: superView.centerXAnchor).isActive = true
subView.centerYAnchor.constraint(equalTo: superView.centerYAnchor).isActive = true
}
最后,我在这里建立平移手势的功能:
// pan functionality for swiping on superview
func handlePan(gesture: UIPanGestureRecognizer) {
guard let superview = gesture.view else {
return
}
// point you are tapped on
let point = gesture.translation(in: view)
// reference for how far left or right of the center of the superview your pan is
let xFromCenter = superview.center.x - view.center.x
// allows the superview to move with your finger
superview.center = CGPoint(x: view.center.x + point.x, y: view.center.y + point.y)
// dragged right
if xFromCenter > 0 {
subView.image = #imageLiteral(resourceName: "yes")
subView.tintColor = UIColor.green
// else dragged left
} else {
subView.image = #imageLiteral(resourceName: "no")
subView.tintColor = UIColor.red
}
// when you let go
if gesture.state == UIGestureRecognizerState.ended {
// animate superview back to center where it originally was
UIView.animate(withDuration: 0.2) {
superview.center = self.view.center
}
}
}
在我添加子视图之前(以及当我将其注释掉时),平移手势在超级视图上工作得很好。但是,当我将子视图限制在超级视图的中心并尝试在视图控制器周围移动超级视图时,它的行为很奇怪(只正确地向左移动,向右移动时不断地回到中心)。
非常感谢任何帮助。
在您的子视图上禁用 userinteraction
,我认为它会起作用!
你的代码应该是这样的,
subView.isUserInteractionEnabled = false
我想通了这个问题。虽然我不知道这是修复的原因,但问题在于我用于向左平移容器视图的 "no" 选项的图像导致整个视图行为异常,因为它是不同的图像。
无论您是向左还是向右平移视图,我都通过设置两个选项 "yes" 来对此进行了测试。这解决了让我相信问题是图像根据您是向左滑动还是向右滑动而切换的问题。我不知道为什么它在显示两个不同的图像时会出现问题,但我也会尝试解决这个问题。
感谢您提供的所有有用信息!