英文:
Applying UIPanGestureRecognizer outside of bounds
问题
我想允许用户向UIScrollView添加一个黄色的正方形UIView,然后既可以拖放又可以缩放用户创建的黄色正方形。
我理解要实现这一点,我需要创建一个次要的视图,比如yellowSquareContainerView,然后进行如下设置:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return yellowSquareContainerView
}
我将黄色正方形添加到这个容器视图中。
然而,这种方法的主要问题是,如果用户将正方形移出yellowSquareContainerView的边界(这是一个完全有效的用例),则添加到黄色UIView的UIPanGestureRecognizer不起作用。
如何使UIPanGestureRecognizer在黄色正方形超出容器视图边界时仍然起作用?
英文:
I want to allow users to add a yellow square UIView to a UIScrollView and then both drag and drop and zoom the yellow squares that the user has created.
I understand that to enable this I need to create a secondary view, say yellowSquareContainerView that I then set up as follows:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return yellowSquareContainerView
}
I add the yellow squares to this container view.
However the main problem with this approach is that the UIPanGestureRecognizer added to the yellow UIView doesn't work if the user moves the square outside of the bounds of the yellowSquareContainerView (which is a completely valid use case).
How can I get the UIPanGestureRecognizer to work when the yellow squares are outside of the bounds of the container view?
答案1
得分: 1
经过一番尝试,我找到了一种超越父视图边界的视图平移方法。这涉及到覆盖父视图的 point
函数。
在内部,视图使用其点函数来确定是否允许事件(例如触摸或平移)。默认情况下,点函数检查事件是否在视图的边界内开始。这就是为什么你可以将视图平移到其父视图之外,但之后就不能再平移了。通过覆盖点函数始终返回 true,手势就始终被允许。
以下是步骤:
1)创建一个 UIView 的子类
2)覆盖 point(inside:with:)
方法,始终返回 true
3)将你的容器视图设置为这个子类的成员
这是一个示例子类:
class ContainerView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return true
}
}
这是一些演示的示例代码:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let containerView = ContainerView(frame: CGRect(x: 100, y: 300, width: 200, height: 200))
containerView.backgroundColor = .green
view.addSubview(containerView)
let yellowSquareView = UIView(frame: CGRect(x: 40, y: 40, width: 80, height: 80))
yellowSquareView.backgroundColor = .yellow
containerView.addSubview(yellowSquareView)
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
yellowSquareView.addGestureRecognizer(pan)
}
@objc private func handlePan(recognizer: UIPanGestureRecognizer) {
if let pannedView = recognizer.view {
let translation = recognizer.translation(in: view)
pannedView.center = CGPoint(x: pannedView.center.x + translation.x,
y: pannedView.center.y + translation.y)
recognizer.setTranslation(.zero, in: view)
}
}
}
英文:
After hacking around, I figured out an approach to panning a view outside the bounds of its parent view. It involves overriding the parent view's point
function.
Internally, a view uses its point function to determine if an event (like touch or pan) should be allowed. By default, point checks if the event starts in the view's bounds. That's why you can pan a view outside of its parent, but you can't pan it after that. By overriding point to always return true, the gesture is always allowed.
Here are the steps:
- Create a subclass of UIView
- Override
point(inside:with:)
to always return true - Make your container view a member of this subclass
Here is an example subclass:
class ContainerView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return true
}
}
And here is some example code to demonstrate:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let containerView = ContainerView(frame: CGRect(x: 100, y: 300, width: 200, height: 200))
containerView.backgroundColor = .green
view.addSubview(containerView)
let yellowSquareView = UIView(frame: CGRect(x: 40, y: 40, width: 80, height: 80))
yellowSquareView.backgroundColor = .yellow
containerView.addSubview(yellowSquareView)
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
yellowSquareView.addGestureRecognizer(pan)
}
@objc private func handlePan(recognizer: UIPanGestureRecognizer) {
if let pannedView = recognizer.view {
let translation = recognizer.translation(in: view)
pannedView.center = CGPoint(x: pannedView.center.x + translation.x,
y: pannedView.center.y + translation.y)
recognizer.setTranslation(.zero, in: view)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论