solenoid
solenoid

Reputation: 1022

UIView Partially Outside superView Not Receiving Touches

Issue: The viewWithGesture contains the viewUserSees, and is draggable within the blue containerView. However, the viewWithGesture is a subView of the containerView, so when the viewWithGesture is at an extreme (illustrated here - half in and half out of the containerView), only half of the viewWithGesture responds to touches, making it very hard to drag.

Note: I realize I should redo all the math that keeps it in the container and move it outside of the containerView, but I am very curious to learn how to do this the "worse" way.

I have researched this a bunch and tried to implement hittest() and pointInside(), but so far I have managed to just make the app crash spectacularly.

Is there a good, relatively clean way to let the user grab from outside the containerView? (swift3 if possible)

EDIT: The green box is transparent and half of it is in the containerView and half is not.

stupid problem

Upvotes: 3

Views: 958

Answers (1)

rob mayoff
rob mayoff

Reputation: 385970

In order for a view to receive a touch, the view and all its ancestors must return true from pointInside:withEvent:.

Normally, pointInside:withEvent: returns false if the point is outside the view's bounds. Since a touch in the green area is outside the container view's bounds, the container view returns false, so the touch won't hit the gesture view.

To fix this, you need to create a subclass for the container view and override its pointInside:withEvent:. In your override, return true if the point is in the container view's bounds or in the gesture view's bounds. Perhaps you can be lazy (especially if your container view doesn't have many subviews) and just return true if the point is in any subview's bounds.

class ContainerView: UIView {

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        if super.point(inside: point, with: event) { return true }
        for subview in subviews {
            let subviewPoint = subview.convert(point, from: self)
            if subview.point(inside: subviewPoint, with: event) { return true }
        }
        return false
    }

}

Upvotes: 7

Related Questions