У меня есть контейнер, для которого clipToBounds
установлено значение false, и представление за его пределами. События касания не распознаются для просмотров за пределами границ.
Как включить прикосновения к представлению за пределами его супервизора?
Ответы (2)
просто добавьте этот класс в свой вид
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
}
}
person
Sandeep Baddula
schedule
12.06.2018
Спасибо, но я искал решение, которое не включает подклассы, так как у меня есть многоразовое представление, которое будет иметь компоненты за пределами границ. Было бы неправильным подходом к подклассу каждого представления для каждого контроллера представления, где я хочу добавить представление, содержащее компонент за пределами границ.
- person Adrian; 18.06.2018
Вот расширение, которое позволит вам разрешить прикосновения к обрезанным подпредставлениям в контейнере. Вставьте этот файл в свой проект и установите 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)
}
}
person
Efraim
schedule
18.06.2018
swizzle(forClass: aClass, originalSelector: originalSelector, swizzledSelector: swizzledSelector) Эта строка не работает.
- person Kishan Lal; 25.10.2018
Не компилируется. Что такое свизл?
- person Jameson; 27.01.2019