我有一个容器,它的clipToBounds设置为false,并且有一个视图超出了它的边界。触摸事件无法识别超出边界的视图。
clipToBounds
z3yyvxxp1#
只需将该类添加到视图中
class MyView: UIView { override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { for subview in subviews as [UIView] { if !subview.isHidden && subview.alpha > 0 && subview.isUserInteractionEnabled && subview.point(inside: convert(point, to: subview), with: event) { return true } } return false } }
n7taea2i2#
这里我修正了之前答案的格式和混合方法
extension UIView { private enum ExtendedTouchAssociatedKey { static var outsideOfBounds = "viewExtensionAllowTouchesOutsideOfBounds" } /// This propery is set on the parent of the view that first clips the content you want to be touchable outside of the bounds var allowTouchesOfViewsOutsideBounds: Bool { get { objc_getAssociatedObject(self, &ExtendedTouchAssociatedKey.outsideOfBounds) as? Bool ?? false } set { UIView.swizzlePointInsideIfNeeded() subviews.forEach { $0.allowTouchesOfViewsOutsideBounds = newValue } objc_setAssociatedObject(self, &ExtendedTouchAssociatedKey.outsideOfBounds, newValue, .OBJC_ASSOCIATION_RETAIN) } } func hasSubview(at point: CGPoint) -> Bool { if subviews.isEmpty { return bounds.contains(point) } return subviews.contains { subview in let converted = self.convert(point, to: subview) return subview.hasSubview(at: converted) } } private static var swizzledMethods = false @objc func _point(inside point: CGPoint, with event: UIEvent?) -> Bool { if allowTouchesOfViewsOutsideBounds { return originalPoint(inside: point, with: event) || hasSubview(at: point) } return originalPoint(inside: point, with: event) } @objc func originalPoint(inside point: CGPoint, with event: UIEvent?) -> Bool { fatalError("this should be swizzled") } private static func swizzlePointInsideIfNeeded() { if swizzledMethods { return } swizzledMethods = true let aClass = UIView.self let originalSelector = class_getInstanceMethod( aClass, #selector(point(inside:with:)) )! let swizzledSelector = class_getInstanceMethod( aClass, #selector(_point(inside:with:)) )! let backupSelector = class_getInstanceMethod( aClass, #selector(originalPoint(inside:with:)) )! let nativeImplementation = method_getImplementation(originalSelector) let customImplementation = method_getImplementation(swizzledSelector) method_setImplementation(originalSelector, customImplementation) method_setImplementation(backupSelector, nativeImplementation) } }
rjjhvcjd3#
这是一个扩展,允许你在一个容器中点击剪切的子视图。将这个文件粘贴到你的项目中并设置containerView.allowTouchesOfViewsOutsideBounds = true
containerView.allowTouchesOfViewsOutsideBounds = true
public extension UIView { private struct ExtendedTouchAssociatedKey { static var outsideOfBounds = "viewExtensionAllowTouchesOutsideOfBounds" } /// This propery is set on the parent of the view that first clips the content you want to be touchable /// outside of the bounds var allowTouchesOfViewsOutsideBounds:Bool { get { return objc_getAssociatedObject(self, &ExtendedTouchAssociatedKey.outsideOfBounds) as? Bool ?? false } set { UIView.swizzlePointInsideIfNeeded() subviews.forEach({$0.allowTouchesOfViewsOutsideBounds = newValue}) objc_setAssociatedObject(self, &ExtendedTouchAssociatedKey.outsideOfBounds, newValue, .OBJC_ASSOCIATION_RETAIN) } } func hasSubview(at point:CGPoint) -> Bool { if subviews.count == 0 { return self.bounds.contains(point) } return subviews.contains(where: { (subview) -> Bool in let converted = self.convert(point, to: subview) return subview.hasSubview(at: converted) }) } static private var swizzledMethods:Bool = false @objc func _point(inside point: CGPoint, with event: UIEvent?) -> Bool { if allowTouchesOfViewsOutsideBounds { return _point(inside:point,with:event) || hasSubview(at: point) } return _point(inside:point,with:event) } static private func swizzlePointInsideIfNeeded() { if swizzledMethods { return } swizzledMethods = true let aClass: AnyClass! = UIView.self let originalSelector = #selector(point(inside:with:)) let swizzledSelector = #selector(_point(inside:with:)) swizzle(forClass: aClass, originalSelector: originalSelector, swizzledSelector: swizzledSelector) } }
3条答案
按热度按时间z3yyvxxp1#
只需将该类添加到视图中
n7taea2i2#
这里我修正了之前答案的格式和混合方法
rjjhvcjd3#
这是一个扩展,允许你在一个容器中点击剪切的子视图。将这个文件粘贴到你的项目中并设置
containerView.allowTouchesOfViewsOutsideBounds = true